Skip to content

Commit 7fdcbba

Browse files
authored
Add high level bindings for js (Z3Prover#6048)
* [Draft] Added unfinished code for high level bindings for js * * Rewrote structure of js api files * Added more high level apis * Minor fixes * Fixed wasm github action * Fix JS test * Removed ContextOptions type * * Added Ints to JS Api * Added tests to JS Api * Added run-time checks for contexts * Removed default contexts * Merged Context and createContext so that the api behaves the sames as in other constructors * Added a test for Solver * Added Reals * Added classes for IntVals and RealVals * Added abillity to specify logic for solver * Try to make CI tests not fail * Changed APIs after a round of review * Fix test * Added BitVectors * Made sort into getter * Added initial JS docs * Added more coercible types * Removed done TODOs
1 parent 3d00d1d commit 7fdcbba

37 files changed

+15974
-644
lines changed

.github/workflows/wasm-release.yml

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -23,8 +23,8 @@ jobs:
2323
- name: Setup node
2424
uses: actions/setup-node@v3
2525
with:
26-
node-version: 'lts/*'
27-
registry-url: 'https://registry.npmjs.org'
26+
node-version: "lts/*"
27+
registry-url: "https://registry.npmjs.org"
2828

2929
- name: Prepare for publish
3030
run: |
@@ -37,13 +37,13 @@ jobs:
3737
with:
3838
no-install: true
3939
version: ${{env.EM_VERSION}}
40-
actions-cache-folder: 'emsdk-cache'
40+
actions-cache-folder: "emsdk-cache"
4141

4242
- name: Install dependencies
4343
run: npm ci
4444

4545
- name: Build TypeScript
46-
run: npm run build-ts
46+
run: npm run build:ts
4747

4848
- name: Build wasm
4949
run: |
@@ -52,7 +52,7 @@ jobs:
5252
source $(dirname $(which emsdk))/emsdk_env.sh
5353
which node
5454
which clang++
55-
npm run build-wasm
55+
npm run build:wasm
5656
5757
- name: Test
5858
run: npm test

.github/workflows/wasm.yml

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ name: WebAssembly Build
22

33
on:
44
push:
5-
branches: [ master ]
5+
branches: [master]
66
pull_request:
77

88
defaults:
@@ -23,20 +23,20 @@ jobs:
2323
- name: Setup node
2424
uses: actions/setup-node@v3
2525
with:
26-
node-version: 'lts/*'
26+
node-version: "lts/*"
2727

2828
- name: Setup emscripten
2929
uses: mymindstorm/setup-emsdk@v11
3030
with:
3131
no-install: true
3232
version: ${{env.EM_VERSION}}
33-
actions-cache-folder: 'emsdk-cache'
33+
actions-cache-folder: "emsdk-cache"
3434

3535
- name: Install dependencies
3636
run: npm ci
3737

3838
- name: Build TypeScript
39-
run: npm run build-ts
39+
run: npm run build:ts
4040

4141
- name: Build wasm
4242
run: |
@@ -45,7 +45,7 @@ jobs:
4545
source $(dirname $(which emsdk))/emsdk_env.sh
4646
which node
4747
which clang++
48-
npm run build-wasm
48+
npm run build:wasm
4949
5050
- name: Test
5151
run: npm test

.gitignore

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,7 @@ src/api/python/z3/z3consts.py
6666
src/api/python/z3/z3core.py
6767
src/ast/pattern/database.h
6868
src/util/version.h
69+
src/util/z3_version.h
6970
src/api/java/Native.cpp
7071
src/api/java/Native.java
7172
src/api/java/enumerations/*.java
@@ -76,11 +77,8 @@ src/api/ml/z3native.mli
7677
src/api/ml/z3enums.mli
7778
src/api/ml/z3.mllib
7879
src/api/js/node_modules/
79-
src/api/js/*.js
8080
src/api/js/build/
81-
src/api/js/**/*.d.ts
82-
!src/api/js/scripts/*.js
83-
!src/api/js/src/*.js
81+
src/api/js/**/*.__GENERATED__.*
8482
debug/*
8583

8684
out/**
@@ -92,3 +90,4 @@ examples/**/obj
9290
CMakeSettings.json
9391
# Editor temp files
9492
*.swp
93+
.DS_Store

doc/mk_api_doc.py

Lines changed: 34 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,11 +14,13 @@
1414

1515
ML_ENABLED=False
1616
MLD_ENABLED=False
17+
JS_ENABLED=False
1718
BUILD_DIR='../build'
1819
DOXYGEN_EXE='doxygen'
1920
TEMP_DIR=os.path.join(os.getcwd(), 'tmp')
2021
OUTPUT_DIRECTORY=os.path.join(os.getcwd(), 'api')
2122
Z3PY_PACKAGE_PATH='../src/api/python/z3'
23+
JS_API_PATH='../src/api/js'
2224
Z3PY_ENABLED=True
2325
DOTNET_ENABLED=True
2426
JAVA_ENABLED=True
@@ -28,8 +30,8 @@
2830

2931
def parse_options():
3032
global ML_ENABLED, MLD_ENABLED, BUILD_DIR, DOXYGEN_EXE, TEMP_DIR, OUTPUT_DIRECTORY
31-
global Z3PY_PACKAGE_PATH, Z3PY_ENABLED, DOTNET_ENABLED, JAVA_ENABLED
32-
global DOTNET_API_SEARCH_PATHS, JAVA_API_SEARCH_PATHS
33+
global Z3PY_PACKAGE_PATH, Z3PY_ENABLED, DOTNET_ENABLED, JAVA_ENABLED, JS_ENABLED
34+
global DOTNET_API_SEARCH_PATHS, JAVA_API_SEARCH_PATHS, JS_API_PATH
3335
parser = argparse.ArgumentParser(description=__doc__)
3436
parser.add_argument('-b',
3537
'--build',
@@ -46,6 +48,11 @@ def parse_options():
4648
default=False,
4749
help='Include ML/OCaml API documentation'
4850
)
51+
parser.add_argument('--js',
52+
action='store_true',
53+
default=False,
54+
help='Include JS/TS API documentation'
55+
)
4956
parser.add_argument('--doxygen-executable',
5057
dest='doxygen_executable',
5158
default=DOXYGEN_EXE,
@@ -104,6 +111,7 @@ def parse_options():
104111
pargs = parser.parse_args()
105112
ML_ENABLED = pargs.ml
106113
MLD_ENABLED = pargs.mld
114+
JS_ENABLED = pargs.js
107115
BUILD_DIR = pargs.build
108116
DOXYGEN_EXE = pargs.doxygen_executable
109117
TEMP_DIR = pargs.temp_dir
@@ -224,6 +232,10 @@ def doc_path(path):
224232
print("Java documentation disabled")
225233
doxygen_config_substitutions['JAVA_API_FILES'] = ''
226234
doxygen_config_substitutions['JAVA_API_SEARCH_PATHS'] = ''
235+
if JS_ENABLED:
236+
print('Javascript documentation enabled')
237+
else:
238+
print('Javascript documentation disabled')
227239

228240
doxygen_config_file = temp_path('z3api.cfg')
229241
configure_file(
@@ -241,7 +253,7 @@ def doc_path(path):
241253
'{prefix}<a class="el" href="z3__api_8h.html">C API</a> '
242254
).format(
243255
prefix=bullet_point_prefix)
244-
256+
245257
if Z3PY_ENABLED:
246258
print("Python documentation enabled")
247259
website_dox_substitutions['PYTHON_API'] = (
@@ -274,6 +286,13 @@ def doc_path(path):
274286
prefix=bullet_point_prefix)
275287
else:
276288
website_dox_substitutions['OCAML_API'] = ''
289+
if JS_ENABLED:
290+
website_dox_substitutions['JS_API'] = (
291+
'{prefix}<a class="el" href="js/index.html">Javascript/Typescript API</a>'
292+
).format(
293+
prefix=bullet_point_prefix)
294+
else:
295+
website_dox_substitutions['JS_API'] = ''
277296
configure_file(
278297
doc_path('website.dox.in'),
279298
temp_path('website.dox'),
@@ -339,6 +358,18 @@ def doc_path(path):
339358
exit(1)
340359
print("Generated ML/OCaml documentation.")
341360

361+
if JS_ENABLED:
362+
try:
363+
subprocess.check_output(['npm', 'run', '--prefix=%s' % JS_API_PATH, 'check-engine'])
364+
except subprocess.CalledProcessError as e:
365+
print("ERROR: node version check failed.")
366+
print(e.output)
367+
exit(1)
368+
if subprocess.call(['npm', 'run', '--prefix=%s' % JS_API_PATH, 'docs']) != 0:
369+
print("ERROR: npm run docs failed.")
370+
exit(1)
371+
print("Generated Javascript documentation.")
372+
342373
print("Documentation was successfully generated at subdirectory '{}'.".format(OUTPUT_DIRECTORY))
343374
except Exception:
344375
exctype, value = sys.exc_info()[:2]

doc/website.dox.in

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,13 @@
11
/**
22
\mainpage An Efficient Theorem Prover
3-
3+
44
Z3 is a high-performance theorem prover being developed at <a class="el"
5-
href="http://research.microsoft.com">Microsoft Research</a>.
6-
5+
href="http://research.microsoft.com">Microsoft Research</a>.
6+
77
<b>The Z3 website is at <a class="el" href="http://github.com/z3prover">http://github.com/z3prover</a>.</b>
88

99
This website hosts the automatically generated documentation for the Z3 APIs.
1010

1111
- \ref @C_API@
12-
- \ref @CPP_API@ @DOTNET_API@ @JAVA_API@ @PYTHON_API@ @OCAML_API@
12+
- \ref @CPP_API@ @DOTNET_API@ @JAVA_API@ @PYTHON_API@ @OCAML_API@ @JS_API@
1313
*/

scripts/mk_util.py

Lines changed: 25 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -246,10 +246,13 @@ def rmf(fname):
246246

247247
def exec_compiler_cmd(cmd):
248248
r = exec_cmd(cmd)
249-
if is_windows() or is_cygwin_mingw() or is_cygwin() or is_msys2():
250-
rmf('a.exe')
251-
else:
252-
rmf('a.out')
249+
# Windows
250+
rmf('a.exe')
251+
# Unix
252+
rmf('a.out')
253+
# Emscripten
254+
rmf('a.wasm')
255+
rmf('a.worker.js')
253256
return r
254257

255258
def test_cxx_compiler(cc):
@@ -293,6 +296,10 @@ def test_fpmath(cc):
293296
t.commit()
294297
# -Werror is needed because some versions of clang warn about unrecognized
295298
# -m flags.
299+
# TODO(ritave): Safari doesn't allow SIMD WebAssembly extension, add a flag to build script
300+
if exec_compiler_cmd([cc, CPPFLAGS, '-Werror', 'tstsse.cpp', LDFLAGS, '-msse -msse2 -msimd128']) == 0:
301+
FPMATH_FLAGS='-msse -msse2 -msimd128'
302+
return 'SSE2-EMSCRIPTEN'
296303
if exec_compiler_cmd([cc, CPPFLAGS, '-Werror', 'tstsse.cpp', LDFLAGS, '-mfpmath=sse -msse -msse2']) == 0:
297304
FPMATH_FLAGS="-mfpmath=sse -msse -msse2"
298305
return "SSE2-GCC"
@@ -499,7 +506,7 @@ def find_ml_lib():
499506

500507
def is64():
501508
global LINUX_X64
502-
if is_sunos() and sys.version_info.major < 3:
509+
if is_sunos() and sys.version_info.major < 3:
503510
return LINUX_X64
504511
else:
505512
return LINUX_X64 and sys.maxsize >= 2**32
@@ -625,11 +632,11 @@ def check_eol():
625632
else:
626633
LINUX_X64=False
627634

628-
635+
629636
if os.name == 'posix' and os.uname()[4] == 'arm64':
630637
IS_ARCH_ARM64 = True
631638

632-
639+
633640
def display_help(exit_code):
634641
print("mk_make.py: Z3 Makefile generator\n")
635642
print("This script generates the Makefile for the Z3 theorem prover.")
@@ -792,7 +799,7 @@ def extract_c_includes(fname):
792799
linenum = 1
793800
for line in f:
794801
m1 = std_inc_pat.match(line)
795-
if m1:
802+
if m1:
796803
root_file_name = m1.group(1)
797804
slash_pos = root_file_name.rfind('/')
798805
if slash_pos >= 0 and root_file_name.find("..") < 0 : #it is a hack for lp include files that behave as continued from "src"
@@ -1650,7 +1657,7 @@ def set_key_file(self):
16501657
else:
16511658
print("Keyfile '%s' could not be found; %s.dll will be unsigned." % (self.key_file, self.dll_name))
16521659
self.key_file = None
1653-
1660+
16541661

16551662
# build for dotnet core
16561663
class DotNetDLLComponent(Component):
@@ -1664,7 +1671,7 @@ def __init__(self, name, dll_name, path, deps, assembly_info_dir, default_key_fi
16641671
self.assembly_info_dir = assembly_info_dir
16651672
self.key_file = default_key_file
16661673

1667-
1674+
16681675
def mk_makefile(self, out):
16691676
if not is_dotnet_core_enabled():
16701677
return
@@ -1680,7 +1687,7 @@ def mk_makefile(self, out):
16801687
out.write(' ')
16811688
out.write(cs_file)
16821689
out.write('\n')
1683-
1690+
16841691
set_key_file(self)
16851692
key = ""
16861693
if not self.key_file is None:
@@ -1724,7 +1731,7 @@ def mk_makefile(self, out):
17241731
ous.write(core_csproj_str)
17251732

17261733
dotnetCmdLine = [DOTNET, "build", csproj]
1727-
1734+
17281735
dotnetCmdLine.extend(['-c'])
17291736
if DEBUG_MODE:
17301737
dotnetCmdLine.extend(['Debug'])
@@ -1733,19 +1740,19 @@ def mk_makefile(self, out):
17331740

17341741
path = os.path.join(os.path.abspath(BUILD_DIR), ".")
17351742
dotnetCmdLine.extend(['-o', "\"%s\"" % path])
1736-
1743+
17371744
MakeRuleCmd.write_cmd(out, ' '.join(dotnetCmdLine))
1738-
out.write('\n')
1745+
out.write('\n')
17391746
out.write('%s: %s\n\n' % (self.name, dllfile))
17401747

17411748
def main_component(self):
17421749
return is_dotnet_core_enabled()
1743-
1750+
17441751
def has_assembly_info(self):
17451752
# TBD: is this required for dotnet core given that version numbers are in z3.csproj file?
17461753
return False
17471754

1748-
1755+
17491756
def mk_win_dist(self, build_path, dist_path):
17501757
if is_dotnet_core_enabled():
17511758
mk_dir(os.path.join(dist_path, INSTALL_BIN_DIR))
@@ -2038,7 +2045,7 @@ def mk_makefile(self, out):
20382045
out.write('ml: %s.cma %s.cmxa %s.cmxs\n' % (z3mls, z3mls, z3mls))
20392046
if IS_OSX:
20402047
out.write('\tinstall_name_tool -id %s/libz3.dylib libz3.dylib\n' % (stubs_install_path))
2041-
out.write('\tinstall_name_tool -change libz3.dylib %s/libz3.dylib api/ml/dllz3ml.so\n' % (stubs_install_path))
2048+
out.write('\tinstall_name_tool -change libz3.dylib %s/libz3.dylib api/ml/dllz3ml.so\n' % (stubs_install_path))
20422049
out.write('\n')
20432050

20442051
if IS_WINDOWS:
@@ -3117,7 +3124,7 @@ def get_platform_toolset_str():
31173124
if len(tokens) < 2:
31183125
return default
31193126
else:
3120-
if tokens[0] == "15":
3127+
if tokens[0] == "15":
31213128
# Visual Studio 2017 reports 15.* but the PlatformToolsetVersion is 141
31223129
return "v141"
31233130
else:

src/api/js/.nvmrc

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
v16.15.0

src/api/js/.prettierrc.json

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
{
2+
"singleQuote": true,
3+
"arrowParens": "avoid",
4+
"printWidth": 120,
5+
"trailingComma": "all"
6+
}

0 commit comments

Comments
 (0)