├── editor └── vscode │ ├── license.txt │ ├── .vscode │ └── launch.json │ ├── package.json │ └── readme.md ├── test ├── end-to-end │ ├── parse-errors │ │ ├── a.txt │ │ ├── type-bracket-unclosed.crow │ │ ├── import-missing-name.crow │ │ ├── interpolated-empty.crow │ │ ├── type-mut.crow │ │ ├── spec-signature-unfinished.crow │ │ ├── unexpected-backslash.crow │ │ ├── unfinished-string-interpolation.crow │ │ ├── enum-missing-name-value.crow │ │ ├── import-file-missing-type.crow │ │ ├── params-missing-end.crow │ │ ├── line-continuation-invalid.crow │ │ ├── interpolated-string-literal-bad-position.crow │ │ ├── type-parens.crow │ │ ├── invalid-utf8.crow │ │ ├── trailing-comma.crow │ │ ├── need-block-context.crow │ │ ├── params-missing-end.crow.out │ │ ├── trailing-comma.crow.out │ │ ├── interpolated-empty.crow.out │ │ ├── line-continuation-invalid.crow.out │ │ ├── invalid-utf8.crow.out │ │ ├── unexpected-backslash.crow.out │ │ ├── type-mut.crow.out │ │ ├── interpolated-string-literal-bad-position.crow.out │ │ ├── import-missing-name.crow.out │ │ ├── type-parens.crow.out │ │ ├── spec-signature-unfinished.crow.out │ │ ├── unfinished-string-interpolation.crow.out │ │ ├── import-file-missing-type.crow.out │ │ ├── type-bracket-unclosed.crow.out │ │ ├── string-escape-invalid.crow │ │ ├── enum-missing-name-value.crow.out │ │ ├── need-block-context.crow.out │ │ └── string-escape-invalid.crow.out │ ├── compile-errors │ │ ├── main-missing.crow │ │ ├── flags-signed.crow.out │ │ ├── function-missing-body.crow │ │ ├── import-non-existing.crow │ │ ├── local-ignored-but-mutable.crow │ │ ├── destructure-non-tuple.crow │ │ ├── bogus-local.crow │ │ ├── cant-infer-type-args.crow │ │ ├── literal-does-not-match-expected-type.crow │ │ ├── circular-import-a.crow │ │ ├── circular-import-b.crow │ │ ├── fun-pointer-not-found.crow │ │ ├── main-duplicate.crow │ │ ├── match-case-missing-name.crow │ │ ├── cant-import-crow-as-string.crow │ │ ├── flags-signed.crow │ │ ├── spec-decl-recursion.crow │ │ ├── library-not-configured.crow │ │ ├── spec-errors.crow │ │ ├── function-pointer-lambda.crow │ │ ├── string-js-any.crow │ │ ├── string-literal-invalid.crow │ │ ├── type-param-cant-have-type-args.crow │ │ ├── not-utf8.txt │ │ ├── type-annotation-unnecessary.crow │ │ ├── variant-member-of-non-variant.crow │ │ ├── alias-not-allowed.crow │ │ ├── duplicate-import.crow │ │ ├── extern-invalid-name.crow │ │ ├── import-non-utf8-as-string.crow │ │ ├── pointer-expression-failed-inference.crow │ │ ├── set-field-of-by-val.crow │ │ ├── variant-member-purity.crow │ │ ├── assert-or-forbid-warnings.crow │ │ ├── mut-param.crow │ │ ├── imported-name-refers-to-nothing.crow │ │ ├── variant-member-template.crow │ │ ├── with-else.crow │ │ ├── fun-cant-have-body.crow │ │ ├── extern-unnecessary-library-name.crow │ │ ├── match-variant-without-else.crow │ │ ├── wrong-number-type-args.crow │ │ ├── option-call-errors.crow │ │ ├── extern-type-errors.crow │ │ ├── fun-cant-have-body.crow.out │ │ ├── record-field-visibility-warnings.crow │ │ ├── loop-disallowed-body.crow │ │ ├── name-not-found.crow │ │ ├── type-params-unsupported.crow │ │ ├── variant-member-multiple.crow │ │ ├── variant-method-impl-visibility.crow │ │ ├── with-else.crow.out │ │ ├── expected-type-param.crow │ │ ├── variant-no-member.crow.out │ │ ├── empty-enum-or-union.crow │ │ ├── local-ignored-but-mutable.crow.out │ │ ├── tuple-too-big.crow │ │ ├── variant-no-member.crow │ │ ├── modifier-conflict.crow │ │ ├── extern-warnings.crow │ │ ├── main-duplicate.crow.out │ │ ├── type-param-cant-have-type-args.crow.out │ │ ├── builtin-does-not-exist.crow │ │ ├── destructure-errors.crow │ │ ├── duplicate-import.crow.out │ │ ├── auto-fun-spec-from-wrong-module.crow.out │ │ ├── function-pointer-not-bare.crow │ │ ├── spec-decl-recursion.crow.out │ │ ├── bogus-local.crow.out │ │ ├── cant-import-crow-as-string.crow.out │ │ ├── extern-redundant.crow │ │ ├── extern-redundant.crow.out │ │ ├── match-variant-without-else.crow.out │ │ ├── set-field-of-by-val.crow.out │ │ ├── variant-member-purity.crow.out │ │ ├── variant-member-template.crow.out │ │ ├── variant-member-wrong-type-arg.crow.out │ │ ├── import-non-utf8-as-string.crow.out │ │ ├── string-js-any.crow.out │ │ ├── fun-pointer-not-found.crow.out │ │ ├── function-pointer-not-bare.crow.out │ │ ├── variant-method-missing.crow │ │ ├── auto-fun-spec-from-wrong-module.crow │ │ ├── main-missing.crow.out │ │ ├── spec-errors.crow.out │ │ ├── spec-inst-recursion.crow │ │ ├── spec-multiple-impls.crow │ │ ├── shared-lambda-errors.crow │ │ ├── spec-use-invalid.crow │ │ ├── variant-multiple-members-with-name.crow │ │ ├── match-case-missing-name.crow.out │ │ ├── variant-member-wrong-type-arg.crow │ │ ├── library-not-configured.crow.out │ │ ├── pointer-expression-failed-inference.crow.out │ │ ├── variant-method-missing.crow.out │ │ ├── function-pointer-lambda.crow.out │ │ ├── imported-name-refers-to-nothing.crow.out │ │ ├── enum-value-overflow.crow │ │ ├── match-warnings.crow │ │ ├── match-warnings.crow.out │ │ ├── auto-fun-flags.crow │ │ ├── lambda-errors.crow │ │ ├── record-privacy-b.crow │ │ ├── cant-infer-type-args.crow.out │ │ ├── mut-param.crow.out │ │ ├── literal-does-not-match-expected-type.crow.out │ │ ├── string-literal-invalid.crow.out │ │ ├── wrong-number-type-args.crow.out │ │ ├── trusted-unnecessary.crow │ │ ├── import-non-existing.crow.out │ │ ├── loop-disallowed-body.crow.out │ │ ├── tuple-too-big.crow.out │ │ ├── variant-member-of-non-variant.crow.out │ │ ├── variant-method-impl-visibility.crow.out │ │ ├── function-missing-body.crow.out │ │ ├── function-pointer-not-supported.crow │ │ ├── empty-enum-or-union.crow.out │ │ ├── pointer-mutability.crow │ │ ├── assert-or-forbid-warnings.crow.out │ │ ├── pointer-mutability.crow.out │ │ ├── record-privacy-a.crow │ │ ├── expected-type-param.crow.out │ │ ├── builtin-does-not-exist.crow.out │ │ ├── auto-fun-errors.crow │ │ ├── call-should-use-syntax.crow │ │ ├── name-not-found.crow.out │ │ ├── extern-warnings.crow.out │ │ ├── modifier-conflict.crow.out │ │ ├── option-call-errors.crow.out │ │ ├── type-annotation-unnecessary.crow.out │ │ ├── extern-type-errors.crow.out │ │ ├── alias-not-allowed.crow.out │ │ ├── fun-closure-errors.crow │ │ ├── spec-multiple-impls.crow.out │ │ ├── extern-unnecessary-library-name.crow.out │ │ ├── lambda-errors.crow.out │ │ ├── variant-multiple-members-with-name.crow.out │ │ ├── modifier-duplicate-or-redundant.crow │ │ ├── call-flags.crow │ │ ├── destructure-errors.crow.out │ │ ├── trusted-unnecessary.crow.out │ │ ├── extern-invalid-name.crow.out │ │ ├── type-params-unsupported.crow.out │ │ ├── variant-member-multiple.crow.out │ │ ├── duplicate-declaration.crow │ │ ├── shared-lambda-errors.crow.out │ │ ├── circular-import-a.crow.out │ │ ├── circular-import-b.crow.out │ │ ├── record-field-visibility-warnings.crow.out │ │ ├── unused.crow │ │ ├── enum-value-overflow.crow.out │ │ ├── extern-errors.crow │ │ ├── spec-inst-recursion.crow.out │ │ ├── auto-fun-flags.crow.out │ │ ├── function-pointer-not-supported.crow.out │ │ ├── spec-use-invalid.crow.out │ │ ├── fun-closure-errors.crow.out │ │ ├── record-privacy-a.crow.out │ │ ├── auto-fun-errors.crow.out │ │ ├── data-spec-with-type-args.crow │ │ └── call-should-use-syntax.crow.out │ └── runnable │ │ ├── main-exit-code-too-big.crow │ │ ├── caught-exception-outside-of-task.crow.out │ │ ├── fail.crow │ │ ├── fail.crow.out │ │ ├── logging.crow.out │ │ ├── main-exit-code-too-big.crow.out │ │ ├── logging.crow │ │ ├── identifiers.crow.out │ │ ├── gc.crow.out │ │ ├── caught-exception-outside-of-task.crow │ │ └── gc.crow ├── test-extern-library │ └── crow-config.json ├── unit │ ├── crow-parser │ │ ├── trailing-indent.crow │ │ ├── strings.crow │ │ ├── no-trailing-comma.crow │ │ ├── line-continuation.crow │ │ ├── pointers.crow │ │ ├── comments.crow │ │ ├── operator-precedence.crow │ │ └── all.crow │ ├── enums.crow │ ├── locals.crow │ ├── variants.crow │ ├── library │ │ ├── symbol-tests.crow │ │ ├── shared-array-tests.crow │ │ ├── shared-map-tests.crow │ │ ├── col │ │ │ ├── array-tests.crow │ │ │ ├── all.crow │ │ │ ├── mut-array-tests.crow │ │ │ ├── set-tests.crow │ │ │ ├── map-tests.crow │ │ │ └── frozen-map-tests.crow │ │ ├── bare-queue-tests.crow │ │ ├── bits-tests.crow │ │ ├── exclusion-queue-tests.crow │ │ ├── all.crow │ │ └── string-tests.crow │ ├── options.crow │ ├── type-cyclic-reference.crow │ ├── file-import.crow │ ├── by-val-or-ref.crow │ ├── loops.crow │ ├── matches.crow │ ├── extern-alignment.crow │ ├── bare-funs.crow │ ├── templates.crow │ ├── log.crow │ ├── pointers.crow │ ├── function-pointers.crow │ ├── globals.crow │ ├── closures.crow │ ├── auto-funs.crow │ ├── flags-tests.crow │ └── parallel.crow ├── failure.crow └── dependencies.crow ├── make.bat ├── site-src ├── tutorial │ └── example.json ├── font │ ├── Alkatra[wght].ttf │ ├── Murecho-Regular.woff2 │ └── Murecho-ExtraBold.woff2 ├── path-and-content.crow ├── play.html ├── script │ ├── util │ │ └── mutable-observable.crow │ ├── index.crow │ ├── decode-tokens.crow │ └── loading-spinner.crow └── search-dir-recursive.crow ├── demo ├── extern │ ├── SDL2 │ │ ├── readme.md │ │ ├── SDL2.dll │ │ ├── SDL2.lib │ │ └── COPYING.txt │ ├── sndfile │ │ ├── readme.md │ │ ├── sndfile.dll │ │ └── sndfile.lib │ └── sqlite3 │ │ └── sqlite3.dll ├── libraries │ ├── SDL2 │ │ ├── crow-config.json │ │ ├── SDL_keyboard.crow │ │ ├── SDL_rect.crow │ │ ├── SDL_rwops.crow │ │ ├── SDL.crow │ │ ├── SDL_surface.crow │ │ ├── SDL_audio.crow │ │ └── SDL_render.crow │ ├── lmdb │ │ └── crow-config.json │ ├── sndfile │ │ ├── crow-config.json │ │ └── util.crow │ ├── sqlite3 │ │ └── crow-config.json │ ├── OpenGL │ │ └── crow-config.json │ └── audio │ │ ├── crow-config.json │ │ ├── audio.crow │ │ └── write-sound-file.crow ├── sdl │ ├── crow.bmp │ └── crow-config.json ├── sound │ ├── crow.wav │ ├── toccata.ogg │ ├── README.md │ ├── crow-config.json │ ├── play-file.crow │ ├── convert-file.crow │ └── main.crow ├── open-gl │ ├── crow.bmp │ ├── crow-config.json │ ├── vertex.vert.essl │ ├── load-bmp.crow │ ├── fragment.frag.essl │ └── texture.crow ├── webapp │ ├── Makefile │ ├── crow-config.json │ ├── index.html │ └── model.crow ├── lmdb │ └── crow-config.json ├── sqlite3 │ ├── crow-config.json │ └── main.crow ├── hello.crow ├── stdin.crow ├── perf.crow ├── parallel.crow ├── server.crow └── time-format.crow ├── src ├── test │ ├── hover │ │ ├── basic.crow │ │ └── function.crow │ ├── testSortUtil.d │ ├── testMemory.d │ ├── testMap.d │ ├── testSymbolSet.d │ ├── testMutMultiMap.d │ └── testWriter.d ├── util │ ├── cell.d │ ├── col │ │ ├── set.d │ │ ├── mapBuilder.d │ │ ├── mutIndexMap.d │ │ ├── stackMap.d │ │ └── mutSet.d │ └── late.d ├── frontend │ ├── lang.d │ └── check │ │ └── maps.d └── concretize │ └── constantsOrExprs.d ├── include ├── system │ ├── bits │ │ ├── sockaddr.crow │ │ └── socket_type.crow │ ├── sys │ │ ├── sysinfo.crow │ │ ├── types.crow │ │ ├── epoll.crow │ │ ├── wait.crow │ │ └── stat.crow │ ├── arpa │ │ └── inet.crow │ ├── stdlib.crow │ ├── string.crow │ ├── errno.crow │ ├── netinet │ │ └── in.crow │ ├── fcntl.crow │ ├── dirent.crow │ ├── sodium.crow │ ├── poll.crow │ ├── time.crow │ ├── unistd.crow │ ├── spawn.crow │ └── stdio.crow └── crow │ ├── crypto │ ├── private │ │ └── sodium.crow │ ├── random.crow │ └── experimental │ │ └── login-cookie.crow │ ├── test-util │ └── test-runner.crow │ ├── io │ ├── posix-util.crow │ ├── terminal-color.crow │ ├── environ.crow │ ├── win32-util.crow │ ├── private │ │ └── time-low-level.crow │ └── duration.crow │ ├── symbol.crow │ ├── fun-util.crow │ ├── bool.crow │ ├── std.crow │ ├── tuple.crow │ ├── col │ ├── private │ │ └── build.crow │ ├── counter.crow │ └── experimental │ │ └── hamt-set.crow │ ├── private │ ├── bool-low-level.crow │ ├── range-low-level.crow │ ├── c-string-util.crow │ └── libunwind.crow │ ├── result.crow │ ├── test-util.crow │ ├── flags-util.crow │ ├── c-types.crow │ └── option.crow ├── .gitignore └── license.md /editor/vscode/license.txt: -------------------------------------------------------------------------------- 1 | public domain -------------------------------------------------------------------------------- /test/end-to-end/parse-errors/a.txt: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /make.bat: -------------------------------------------------------------------------------- 1 | @nmake /nologo /f NMakefile %* 2 | -------------------------------------------------------------------------------- /test/end-to-end/compile-errors/main-missing.crow: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /test/end-to-end/compile-errors/flags-signed.crow.out: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /site-src/tutorial/example.json: -------------------------------------------------------------------------------- 1 | { 2 | "crow": 99 3 | } 4 | -------------------------------------------------------------------------------- /test/end-to-end/parse-errors/type-bracket-unclosed.crow: -------------------------------------------------------------------------------- 1 | f nat[() 2 | -------------------------------------------------------------------------------- /demo/extern/SDL2/readme.md: -------------------------------------------------------------------------------- 1 | From https://www.libsdl.org/download-2.0.php -------------------------------------------------------------------------------- /src/test/hover/basic.crow: -------------------------------------------------------------------------------- 1 | nat builtin 2 | 3 | r record 4 | fld nat 5 | -------------------------------------------------------------------------------- /test/end-to-end/parse-errors/import-missing-name.crow: -------------------------------------------------------------------------------- 1 | import 2 | x: , y 3 | -------------------------------------------------------------------------------- /test/end-to-end/parse-errors/interpolated-empty.crow: -------------------------------------------------------------------------------- 1 | s string() 2 | "{}" 3 | -------------------------------------------------------------------------------- /test/end-to-end/parse-errors/type-mut.crow: -------------------------------------------------------------------------------- 1 | main void() 2 | a nat mut = 0 3 | -------------------------------------------------------------------------------- /test/end-to-end/compile-errors/function-missing-body.crow: -------------------------------------------------------------------------------- 1 | main void() 2 | test 3 | -------------------------------------------------------------------------------- /test/end-to-end/parse-errors/spec-signature-unfinished.crow: -------------------------------------------------------------------------------- 1 | s spec 2 | f void( 3 | -------------------------------------------------------------------------------- /test/end-to-end/parse-errors/unexpected-backslash.crow: -------------------------------------------------------------------------------- 1 | f void() 2 | x :\= 1 3 | -------------------------------------------------------------------------------- /test/end-to-end/parse-errors/unfinished-string-interpolation.crow: -------------------------------------------------------------------------------- 1 | f string() 2 | "{ -------------------------------------------------------------------------------- /demo/libraries/SDL2/crow-config.json: -------------------------------------------------------------------------------- 1 | { 2 | "extern": { 3 | "SDL2": null 4 | } 5 | } -------------------------------------------------------------------------------- /demo/libraries/lmdb/crow-config.json: -------------------------------------------------------------------------------- 1 | { 2 | "extern": { 3 | "lmdb": null 4 | } 5 | } -------------------------------------------------------------------------------- /demo/sdl/crow.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/andy-hanson/crow/HEAD/demo/sdl/crow.bmp -------------------------------------------------------------------------------- /test/end-to-end/compile-errors/import-non-existing.crow: -------------------------------------------------------------------------------- 1 | import 2 | ./does-not-exist 3 | -------------------------------------------------------------------------------- /demo/extern/sndfile/readme.md: -------------------------------------------------------------------------------- 1 | From https://github.com/libsndfile/libsndfile/releases/ 2 | -------------------------------------------------------------------------------- /demo/libraries/sndfile/crow-config.json: -------------------------------------------------------------------------------- 1 | { 2 | "extern": { 3 | "sndfile": null 4 | } 5 | } -------------------------------------------------------------------------------- /demo/libraries/sqlite3/crow-config.json: -------------------------------------------------------------------------------- 1 | { 2 | "extern": { 3 | "sqlite3": null 4 | } 5 | } -------------------------------------------------------------------------------- /demo/sound/crow.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/andy-hanson/crow/HEAD/demo/sound/crow.wav -------------------------------------------------------------------------------- /test/end-to-end/parse-errors/enum-missing-name-value.crow: -------------------------------------------------------------------------------- 1 | e enum 2 | = 1 3 | x = 4 | = 5 | -------------------------------------------------------------------------------- /test/end-to-end/parse-errors/import-file-missing-type.crow: -------------------------------------------------------------------------------- 1 | import 2 | ./a.txt as text 3 | -------------------------------------------------------------------------------- /test/end-to-end/runnable/main-exit-code-too-big.crow: -------------------------------------------------------------------------------- 1 | main nat(_ string[]) 2 | max-value 3 | -------------------------------------------------------------------------------- /demo/open-gl/crow.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/andy-hanson/crow/HEAD/demo/open-gl/crow.bmp -------------------------------------------------------------------------------- /demo/sound/toccata.ogg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/andy-hanson/crow/HEAD/demo/sound/toccata.ogg -------------------------------------------------------------------------------- /test/end-to-end/compile-errors/local-ignored-but-mutable.crow: -------------------------------------------------------------------------------- 1 | main void() 2 | _ mut nat = 0 3 | -------------------------------------------------------------------------------- /test/end-to-end/runnable/caught-exception-outside-of-task.crow.out: -------------------------------------------------------------------------------- 1 | exit code: big 2 | stderr: 3 | -------------------------------------------------------------------------------- /demo/extern/SDL2/SDL2.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/andy-hanson/crow/HEAD/demo/extern/SDL2/SDL2.dll -------------------------------------------------------------------------------- /demo/extern/SDL2/SDL2.lib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/andy-hanson/crow/HEAD/demo/extern/SDL2/SDL2.lib -------------------------------------------------------------------------------- /demo/libraries/SDL2/SDL_keyboard.crow: -------------------------------------------------------------------------------- 1 | +SDL_GetKeyboardState nat8*(num-keys int mut*) SDL2 extern 2 | -------------------------------------------------------------------------------- /test/end-to-end/compile-errors/destructure-non-tuple.crow: -------------------------------------------------------------------------------- 1 | main void() 2 | (x, y) = 1::nat 3 | x, 4 | -------------------------------------------------------------------------------- /test/end-to-end/parse-errors/params-missing-end.crow: -------------------------------------------------------------------------------- 1 | f string( 2 | x 3 | 4 | g nat(x nat) 5 | x 6 | -------------------------------------------------------------------------------- /test/test-extern-library/crow-config.json: -------------------------------------------------------------------------------- 1 | { 2 | "extern": { 3 | "example": "../../bin" 4 | } 5 | } -------------------------------------------------------------------------------- /src/test/hover/function.crow: -------------------------------------------------------------------------------- 1 | nat builtin 2 | 3 | f nat(a nat) 4 | a g 5 | 6 | g nat(a nat) 7 | 0 8 | -------------------------------------------------------------------------------- /test/end-to-end/compile-errors/bogus-local.crow: -------------------------------------------------------------------------------- 1 | main void() summon 2 | x = z 3 | _ nat = x ? 1 : 2 4 | -------------------------------------------------------------------------------- /test/end-to-end/compile-errors/cant-infer-type-args.crow: -------------------------------------------------------------------------------- 1 | f[t] void() 2 | () 3 | 4 | main void() 5 | f 6 | -------------------------------------------------------------------------------- /test/end-to-end/compile-errors/literal-does-not-match-expected-type.crow: -------------------------------------------------------------------------------- 1 | main void() 2 | _ string = 0 3 | -------------------------------------------------------------------------------- /test/end-to-end/compile-errors/circular-import-a.crow: -------------------------------------------------------------------------------- 1 | import 2 | ./circular-import-b 3 | 4 | a int() 5 | 0 6 | -------------------------------------------------------------------------------- /test/end-to-end/compile-errors/circular-import-b.crow: -------------------------------------------------------------------------------- 1 | import 2 | ./circular-import-a 3 | 4 | b int() 5 | 0 6 | -------------------------------------------------------------------------------- /test/end-to-end/compile-errors/fun-pointer-not-found.crow: -------------------------------------------------------------------------------- 1 | main void() 2 | x void function() = &foo 3 | x[] 4 | -------------------------------------------------------------------------------- /test/end-to-end/compile-errors/main-duplicate.crow: -------------------------------------------------------------------------------- 1 | main void() 2 | () 3 | 4 | main nat(_ string[]) 5 | () 6 | -------------------------------------------------------------------------------- /test/end-to-end/compile-errors/match-case-missing-name.crow: -------------------------------------------------------------------------------- 1 | f string() 2 | match ()::nat? 3 | as 4 | 1 5 | -------------------------------------------------------------------------------- /test/end-to-end/parse-errors/line-continuation-invalid.crow: -------------------------------------------------------------------------------- 1 | main void() 2 | info \ log 3 | "hello, world!" 4 | -------------------------------------------------------------------------------- /demo/extern/sndfile/sndfile.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/andy-hanson/crow/HEAD/demo/extern/sndfile/sndfile.dll -------------------------------------------------------------------------------- /demo/extern/sndfile/sndfile.lib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/andy-hanson/crow/HEAD/demo/extern/sndfile/sndfile.lib -------------------------------------------------------------------------------- /demo/extern/sqlite3/sqlite3.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/andy-hanson/crow/HEAD/demo/extern/sqlite3/sqlite3.dll -------------------------------------------------------------------------------- /include/system/bits/sockaddr.crow: -------------------------------------------------------------------------------- 1 | no-std 2 | import 3 | crow/number: nat16 4 | 5 | sa_family_t alias 6 | nat16 7 | -------------------------------------------------------------------------------- /site-src/font/Alkatra[wght].ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/andy-hanson/crow/HEAD/site-src/font/Alkatra[wght].ttf -------------------------------------------------------------------------------- /test/end-to-end/compile-errors/cant-import-crow-as-string.crow: -------------------------------------------------------------------------------- 1 | import 2 | ./cant-infer-type-args.crow as x string 3 | -------------------------------------------------------------------------------- /test/end-to-end/compile-errors/flags-signed.crow: -------------------------------------------------------------------------------- 1 | main void() 2 | () 3 | 4 | f flags int32 storage 5 | x = -1 6 | -------------------------------------------------------------------------------- /test/end-to-end/compile-errors/spec-decl-recursion.crow: -------------------------------------------------------------------------------- 1 | main void() 2 | () 3 | 4 | a spec b 5 | 6 | b spec a 7 | -------------------------------------------------------------------------------- /test/end-to-end/parse-errors/interpolated-string-literal-bad-position.crow: -------------------------------------------------------------------------------- 1 | main void() 2 | info log "{x "y"}" 3 | -------------------------------------------------------------------------------- /include/system/bits/socket_type.crow: -------------------------------------------------------------------------------- 1 | no-std 2 | import 3 | crow/number: int32 4 | 5 | +SOCK_STREAM int32() 6 | 1 7 | -------------------------------------------------------------------------------- /include/system/sys/sysinfo.crow: -------------------------------------------------------------------------------- 1 | no-std 2 | import 3 | crow/c-types: c-int 4 | 5 | +get_nprocs c-int() linux extern 6 | -------------------------------------------------------------------------------- /site-src/font/Murecho-Regular.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/andy-hanson/crow/HEAD/site-src/font/Murecho-Regular.woff2 -------------------------------------------------------------------------------- /test/end-to-end/compile-errors/library-not-configured.crow: -------------------------------------------------------------------------------- 1 | import 2 | non-existent: foo 3 | 4 | main void() 5 | () 6 | -------------------------------------------------------------------------------- /test/end-to-end/compile-errors/spec-errors.crow: -------------------------------------------------------------------------------- 1 | main void() 2 | () 3 | 4 | s spec by-val 5 | x nat(...xs nat array) 6 | -------------------------------------------------------------------------------- /test/unit/crow-parser/trailing-indent.crow: -------------------------------------------------------------------------------- 1 | # This file ends in a tab character 2 | dummy-trailing-indent nat() 3 | 0 4 | -------------------------------------------------------------------------------- /site-src/font/Murecho-ExtraBold.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/andy-hanson/crow/HEAD/site-src/font/Murecho-ExtraBold.woff2 -------------------------------------------------------------------------------- /site-src/path-and-content.crow: -------------------------------------------------------------------------------- 1 | path-and-content record 2 | # relative to 'site' 3 | out-path string 4 | content string 5 | -------------------------------------------------------------------------------- /test/end-to-end/compile-errors/function-pointer-lambda.crow: -------------------------------------------------------------------------------- 1 | main void() 2 | f void function() = () => () 3 | f[] 4 | () 5 | -------------------------------------------------------------------------------- /test/end-to-end/compile-errors/string-js-any.crow: -------------------------------------------------------------------------------- 1 | import 2 | crow/js: js-any 3 | 4 | main void() 5 | _ js-any = "foo" 6 | -------------------------------------------------------------------------------- /test/end-to-end/compile-errors/string-literal-invalid.crow: -------------------------------------------------------------------------------- 1 | main void() 2 | info log "a\0b" 3 | info log "{"a\0b"::symbol}" 4 | -------------------------------------------------------------------------------- /test/end-to-end/compile-errors/type-param-cant-have-type-args.crow: -------------------------------------------------------------------------------- 1 | main void() 2 | () 3 | 4 | f[t] void(_ nat t) 5 | () 6 | -------------------------------------------------------------------------------- /test/end-to-end/parse-errors/type-parens.crow: -------------------------------------------------------------------------------- 1 | f void(a ()) 2 | f void(a () set) 3 | f void(a (nat)) 4 | f void(a (nat) set) 5 | -------------------------------------------------------------------------------- /test/end-to-end/runnable/fail.crow: -------------------------------------------------------------------------------- 1 | main void() 2 | foo 3 | 4 | foo void() 5 | bar 6 | 7 | bar void() 8 | throw "FOO" error 9 | -------------------------------------------------------------------------------- /test/end-to-end/runnable/fail.crow.out: -------------------------------------------------------------------------------- 1 | exit code: 1 2 | stderr: 3 | Uncaught exception: FOO 4 | at bar 5 | at foo 6 | at main 7 | -------------------------------------------------------------------------------- /demo/libraries/SDL2/SDL_rect.crow: -------------------------------------------------------------------------------- 1 | import 2 | crow/c-types: c-int 3 | 4 | +SDL_Rect record(x c-int, y c-int, w c-int, h c-int) extern 5 | -------------------------------------------------------------------------------- /test/end-to-end/compile-errors/not-utf8.txt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/andy-hanson/crow/HEAD/test/end-to-end/compile-errors/not-utf8.txt -------------------------------------------------------------------------------- /test/end-to-end/compile-errors/type-annotation-unnecessary.crow: -------------------------------------------------------------------------------- 1 | main void() 2 | x nat = 0::nat 3 | (info log "{x}"::string)::void 4 | -------------------------------------------------------------------------------- /test/end-to-end/compile-errors/variant-member-of-non-variant.crow: -------------------------------------------------------------------------------- 1 | main void() 2 | _ bool = m 3 | 4 | m record bool variant-member 5 | -------------------------------------------------------------------------------- /demo/webapp/Makefile: -------------------------------------------------------------------------------- 1 | serve: index.js 2 | ./main.crow 3 | 4 | index.js: index.crow model.crow 5 | crow build index.crow --out index.js 6 | -------------------------------------------------------------------------------- /test/end-to-end/compile-errors/alias-not-allowed.crow: -------------------------------------------------------------------------------- 1 | main void() 2 | _ bar = 1, 3 | 4 | foo alias 5 | foo 6 | 7 | bar alias 8 | foo[] 9 | -------------------------------------------------------------------------------- /test/end-to-end/compile-errors/duplicate-import.crow: -------------------------------------------------------------------------------- 1 | import 2 | crow/math/math: pi, pi 3 | 4 | main void() 5 | info log "{pi::float64}" 6 | -------------------------------------------------------------------------------- /test/end-to-end/compile-errors/extern-invalid-name.crow: -------------------------------------------------------------------------------- 1 | main void() 2 | if extern bar 3 | foo 4 | 5 | foo void() bar extern 6 | () 7 | -------------------------------------------------------------------------------- /test/end-to-end/compile-errors/import-non-utf8-as-string.crow: -------------------------------------------------------------------------------- 1 | import 2 | ./not-utf8.txt as s string 3 | 4 | main void() 5 | info log s 6 | -------------------------------------------------------------------------------- /test/end-to-end/compile-errors/pointer-expression-failed-inference.crow: -------------------------------------------------------------------------------- 1 | main void() unsafe 2 | x nat = 0 3 | _ nat8* = (&x).pointer-cast 4 | -------------------------------------------------------------------------------- /demo/lmdb/crow-config.json: -------------------------------------------------------------------------------- 1 | { 2 | "include": { 3 | "lmdb": "../libraries/lmdb" 4 | }, 5 | "extern": { 6 | "lmdb": "system" 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /test/end-to-end/compile-errors/set-field-of-by-val.crow: -------------------------------------------------------------------------------- 1 | main void() 2 | r mut r = 0, 3 | r.x := 3 4 | 5 | r record by-val, mut 6 | x mut nat 7 | -------------------------------------------------------------------------------- /test/end-to-end/compile-errors/variant-member-purity.crow: -------------------------------------------------------------------------------- 1 | main void() 2 | info log "done" 3 | 4 | v variant 5 | m record mut, v variant-member 6 | -------------------------------------------------------------------------------- /test/end-to-end/parse-errors/invalid-utf8.crow: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/andy-hanson/crow/HEAD/test/end-to-end/parse-errors/invalid-utf8.crow -------------------------------------------------------------------------------- /demo/sdl/crow-config.json: -------------------------------------------------------------------------------- 1 | { 2 | "include": { 3 | "SDL2": "../libraries/SDL2" 4 | }, 5 | "extern": { 6 | "SDL2": "../extern/SDL2" 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /demo/webapp/crow-config.json: -------------------------------------------------------------------------------- 1 | { 2 | "include": { 3 | "lmdb": "../libraries/lmdb", 4 | }, 5 | "extern": { 6 | "lmdb": "system", 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /test/end-to-end/compile-errors/assert-or-forbid-warnings.crow: -------------------------------------------------------------------------------- 1 | main void() 2 | assert true : throw divide-by-0 3 | guard true : throw divide-by-0 4 | -------------------------------------------------------------------------------- /test/end-to-end/compile-errors/mut-param.crow: -------------------------------------------------------------------------------- 1 | main void() 2 | x mut nat = 0 3 | x f 4 | info log "{x}" 5 | 6 | f void(a mut nat) 7 | a +:= 1 8 | -------------------------------------------------------------------------------- /test/end-to-end/parse-errors/trailing-comma.crow: -------------------------------------------------------------------------------- 1 | import 2 | crow/io/print: out, print, 3 | 4 | main void() summon 5 | out print "Hello, world!" 6 | -------------------------------------------------------------------------------- /test/end-to-end/runnable/logging.crow.out: -------------------------------------------------------------------------------- 1 | exit code: 0 2 | stdout: 3 | info: Logged once 4 | stderr: 5 | warn: Logged twice 6 | warn: Logged twice 7 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | bin 2 | site 3 | dyncall 4 | editor/vscode/node_modules 5 | test/test 6 | demo/webapp/db 7 | demo/webapp/index.js 8 | demo/webapp/index.js.map 9 | -------------------------------------------------------------------------------- /test/end-to-end/compile-errors/imported-name-refers-to-nothing.crow: -------------------------------------------------------------------------------- 1 | import 2 | crow/parse: foo 3 | 4 | main void() 5 | info log "hello" 6 | info log foo 7 | -------------------------------------------------------------------------------- /test/end-to-end/compile-errors/variant-member-template.crow: -------------------------------------------------------------------------------- 1 | main void() 2 | info log "done" 3 | 4 | -v variant 5 | -x[t] record(value t) v variant-member 6 | -------------------------------------------------------------------------------- /test/end-to-end/compile-errors/with-else.crow: -------------------------------------------------------------------------------- 1 | main nat(_ string[]) 2 | _ void future = with : parallel 3 | info log "inner" 4 | else 5 | info log "else" 6 | -------------------------------------------------------------------------------- /test/end-to-end/runnable/main-exit-code-too-big.crow.out: -------------------------------------------------------------------------------- 1 | exit code: big 2 | stderr: 3 | 'main' must return a number <= 2147483647; got 18446744073709551615 4 | -------------------------------------------------------------------------------- /test/end-to-end/compile-errors/fun-cant-have-body.crow: -------------------------------------------------------------------------------- 1 | main void() 2 | () 3 | 4 | == nat(a nat, b nat) builtin 5 | true 6 | 7 | foo void() libc extern 8 | () 9 | -------------------------------------------------------------------------------- /demo/libraries/OpenGL/crow-config.json: -------------------------------------------------------------------------------- 1 | { 2 | "include": { 3 | "SDL2": "../SDL2" 4 | }, 5 | "extern": { 6 | "GL": null, 7 | "SDL2": null 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /demo/sqlite3/crow-config.json: -------------------------------------------------------------------------------- 1 | { 2 | "include": { 3 | "sqlite3": "../libraries/sqlite3", 4 | }, 5 | "extern": { 6 | "sqlite3": "../extern/sqlite3", 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /test/end-to-end/compile-errors/extern-unnecessary-library-name.crow: -------------------------------------------------------------------------------- 1 | main void() 2 | () 3 | 4 | f flags libc extern 5 | r record libc extern 6 | u union(x) libc extern 7 | -------------------------------------------------------------------------------- /test/end-to-end/compile-errors/match-variant-without-else.crow: -------------------------------------------------------------------------------- 1 | main void() 2 | info log match x 3 | as x 4 | "hello" 5 | 6 | v variant 7 | x record v variant-member 8 | -------------------------------------------------------------------------------- /test/unit/crow-parser/strings.crow: -------------------------------------------------------------------------------- 1 | dummy-strings nat() 2 | 0 3 | 4 | test 5 | "\xe1"::string is "á" 6 | "\u30c3"::string is "ッ" 7 | "\U0001f63c"::string is "😼" 8 | -------------------------------------------------------------------------------- /demo/sound/README.md: -------------------------------------------------------------------------------- 1 | crow.wav from https://soundbible.com/2040-Rooster-Crowing-2.html 2 | tocatta.ogg adapted from https://orangefreesounds.com/toccata-and-fugue-in-d-minor/ 3 | -------------------------------------------------------------------------------- /test/end-to-end/compile-errors/wrong-number-type-args.crow: -------------------------------------------------------------------------------- 1 | main void() 2 | () 3 | 4 | magic[out, in] out?(a in?) 5 | () 6 | 7 | use-it[out, in] out?(a in?) 8 | a magic@out 9 | -------------------------------------------------------------------------------- /test/unit/enums.crow: -------------------------------------------------------------------------------- 1 | dummy-enums nat() 2 | 0 3 | 4 | test 5 | x.to::nat32 is 0 6 | y.to::nat32 is 1 7 | enum-members::(symbol, e)[] is (("x", x), ("y", y)) 8 | -e enum(x, y) 9 | -------------------------------------------------------------------------------- /test/end-to-end/compile-errors/option-call-errors.crow: -------------------------------------------------------------------------------- 1 | main void() 2 | int int = -1 3 | int-opt int? = -1, 4 | x nat? = int?.abs 5 | y nat = int-opt?.abs 6 | z = int?.abs 7 | () 8 | -------------------------------------------------------------------------------- /test/end-to-end/compile-errors/extern-type-errors.crow: -------------------------------------------------------------------------------- 1 | main void() 2 | () 3 | 4 | a extern 5 | 6 | r record 7 | a a 8 | 9 | b[t] extern 10 | 11 | c extern(9999999999, 3) 12 | -------------------------------------------------------------------------------- /test/end-to-end/parse-errors/need-block-context.crow: -------------------------------------------------------------------------------- 1 | f void() 2 | if if 3 | 0 4 | else 5 | 1 6 | match match 7 | as some 8 | 0 9 | as none 10 | 1 11 | match () => 12 | -------------------------------------------------------------------------------- /test/end-to-end/compile-errors/fun-cant-have-body.crow.out: -------------------------------------------------------------------------------- 1 | exit code: 0 2 | stderr: 3 | test/end-to-end/compile-errors/fun-cant-have-body.crow 4:1-4:3 A 'builtin' function can't have a body. 4 | -------------------------------------------------------------------------------- /test/end-to-end/compile-errors/record-field-visibility-warnings.crow: -------------------------------------------------------------------------------- 1 | main void() 2 | () 3 | 4 | r record 5 | +x nat 6 | 7 | -s record 8 | ~x nat 9 | 10 | -t record 11 | -x nat 12 | -------------------------------------------------------------------------------- /test/unit/locals.crow: -------------------------------------------------------------------------------- 1 | dummy-locals nat() 2 | 0 3 | 4 | test 5 | message string = match ("a",)::string? 6 | as some message 7 | message 8 | as none 9 | "b" 10 | message is "a" 11 | -------------------------------------------------------------------------------- /test/end-to-end/compile-errors/loop-disallowed-body.crow: -------------------------------------------------------------------------------- 1 | main void() 2 | loop 3 | try 4 | break 5 | catch divide-by-0 6 | continue 7 | 8 | loop 9 | finally x 10 | break 11 | -------------------------------------------------------------------------------- /test/end-to-end/compile-errors/name-not-found.crow: -------------------------------------------------------------------------------- 1 | main void() 2 | () 3 | 4 | r record 5 | f t 6 | h array x 7 | 8 | u union 9 | t 10 | 11 | foo t() s 12 | x 13 | a y 14 | a z b 15 | -------------------------------------------------------------------------------- /test/end-to-end/compile-errors/type-params-unsupported.crow: -------------------------------------------------------------------------------- 1 | main void() 2 | () 3 | 4 | f[t] void() libc extern 5 | ex[t] extern 6 | seq[t] alias 7 | t[] 8 | e[t] enum(x) 9 | f[t] flags 10 | -------------------------------------------------------------------------------- /test/end-to-end/compile-errors/variant-member-multiple.crow: -------------------------------------------------------------------------------- 1 | main void() 2 | _ nat v = r 3 | _ string v = r 4 | () 5 | 6 | v[t] variant 7 | r record nat v variant-member, string v variant-member 8 | -------------------------------------------------------------------------------- /test/end-to-end/compile-errors/variant-method-impl-visibility.crow: -------------------------------------------------------------------------------- 1 | main void() 2 | info log x.foo 3 | 4 | v variant 5 | foo string() 6 | x record v variant-member 7 | -foo string(_ x) 8 | "x" 9 | -------------------------------------------------------------------------------- /test/end-to-end/compile-errors/with-else.crow.out: -------------------------------------------------------------------------------- 1 | exit code: 0 2 | stdout: 3 | info: inner 4 | stderr: 5 | test/end-to-end/compile-errors/with-else.crow 2:21-2:25 'with' statement can't have 'else'. 6 | -------------------------------------------------------------------------------- /test/end-to-end/parse-errors/params-missing-end.crow.out: -------------------------------------------------------------------------------- 1 | exit code: 1 2 | stderr: 3 | test/end-to-end/parse-errors/params-missing-end.crow 4:1-4:2 Expected ','. 4 | Stopping due to compile errors. 5 | -------------------------------------------------------------------------------- /test/end-to-end/parse-errors/trailing-comma.crow.out: -------------------------------------------------------------------------------- 1 | exit code: 0 2 | stdout: 3 | Hello, world! 4 | stderr: 5 | test/end-to-end/parse-errors/trailing-comma.crow 2:30-2:31 Remove this trailing comma. 6 | -------------------------------------------------------------------------------- /test/unit/crow-parser/no-trailing-comma.crow: -------------------------------------------------------------------------------- 1 | dummy-no-trailing-comma nat() 2 | 0 3 | 4 | test 5 | "a".f is "a" 6 | 7 | # No trailing comma 8 | f string( 9 | a string 10 | ) 11 | a 12 | -------------------------------------------------------------------------------- /demo/libraries/audio/crow-config.json: -------------------------------------------------------------------------------- 1 | { 2 | "include": { 3 | "SDL2": "../SDL2", 4 | "sndfile": "../sndfile" 5 | }, 6 | "extern": { 7 | "SDL2": null, 8 | "sndfile": null 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /demo/open-gl/crow-config.json: -------------------------------------------------------------------------------- 1 | { 2 | "include": { 3 | "OpenGL": "../libraries/OpenGL", 4 | "SDL2": "../libraries/SDL2", 5 | }, 6 | "extern": { 7 | "SDL2": "../extern/SDL2" 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /test/end-to-end/compile-errors/expected-type-param.crow: -------------------------------------------------------------------------------- 1 | main void() 2 | "x"::string foo 3 | "x"::string bar 0::nat64 4 | 5 | foo[t] void(a t) 6 | a bar 0 7 | 8 | bar[t] void(a t, b t) 9 | () 10 | -------------------------------------------------------------------------------- /test/end-to-end/compile-errors/variant-no-member.crow.out: -------------------------------------------------------------------------------- 1 | exit code: 0 2 | stdout: 3 | info: x 4 | stderr: 5 | test/end-to-end/compile-errors/variant-no-member.crow 3:8-3:9 There is no type in scope named 'w'. 6 | -------------------------------------------------------------------------------- /test/end-to-end/compile-errors/empty-enum-or-union.crow: -------------------------------------------------------------------------------- 1 | main void() unsafe 2 | gc-safe-value::e f 3 | 4 | f void(a u) 5 | match a 6 | 7 | f void(a e) 8 | match a 9 | 10 | e enum 11 | 12 | u union 13 | -------------------------------------------------------------------------------- /test/end-to-end/compile-errors/local-ignored-but-mutable.crow.out: -------------------------------------------------------------------------------- 1 | exit code: 0 2 | stderr: 3 | test/end-to-end/compile-errors/local-ignored-but-mutable.crow 2:5-2:14 Unnecessary 'mut' on ignored local variable. 4 | -------------------------------------------------------------------------------- /test/end-to-end/parse-errors/interpolated-empty.crow.out: -------------------------------------------------------------------------------- 1 | exit code: 1 2 | stderr: 3 | test/end-to-end/parse-errors/interpolated-empty.crow 2:6-2:8 Expected an expression here. 4 | Stopping due to compile errors. 5 | -------------------------------------------------------------------------------- /test/end-to-end/compile-errors/tuple-too-big.crow: -------------------------------------------------------------------------------- 1 | main void() 2 | x1, x2, x3, x4, x5, x6, x7, x8, x9, x10 = f 3 | () 4 | 5 | f (nat, nat, nat, nat, nat, nat, nat, nat, nat, nat)() 6 | 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 7 | -------------------------------------------------------------------------------- /test/end-to-end/compile-errors/variant-no-member.crow: -------------------------------------------------------------------------------- 1 | main void() 2 | info log match x 3 | as w 4 | "w" 5 | as x 6 | "x" 7 | else 8 | "other" 9 | 10 | v variant 11 | x record v variant-member 12 | 13 | -------------------------------------------------------------------------------- /test/end-to-end/parse-errors/line-continuation-invalid.crow.out: -------------------------------------------------------------------------------- 1 | exit code: 1 2 | stderr: 3 | test/end-to-end/parse-errors/line-continuation-invalid.crow 2:10-2:11 Expected a dedent. 4 | Stopping due to compile errors. 5 | -------------------------------------------------------------------------------- /include/system/arpa/inet.crow: -------------------------------------------------------------------------------- 1 | no-std 2 | import 3 | crow/string: c-string 4 | ../netinet/in: in_addr, in_addr_t 5 | 6 | +inet_addr in_addr_t(cp c-string) posix extern 7 | 8 | +inet_ntoa c-string(in in_addr) posix extern 9 | -------------------------------------------------------------------------------- /test/end-to-end/compile-errors/modifier-conflict.crow: -------------------------------------------------------------------------------- 1 | main void() 2 | () 3 | 4 | dm extern data, mut 5 | 6 | ms record mut, shared 7 | 8 | sfs record force-shared, shared 9 | 10 | bvbr record by-ref, by-val 11 | -------------------------------------------------------------------------------- /test/end-to-end/parse-errors/invalid-utf8.crow.out: -------------------------------------------------------------------------------- 1 | exit code: 1 2 | stderr: 3 | test/end-to-end/parse-errors/invalid-utf8.crow 1:1-1:1 File is not encoded as UTF-8 or has encoding errors. 4 | Stopping due to compile errors. 5 | -------------------------------------------------------------------------------- /test/end-to-end/parse-errors/unexpected-backslash.crow.out: -------------------------------------------------------------------------------- 1 | exit code: 1 2 | stderr: 3 | test/end-to-end/parse-errors/unexpected-backslash.crow 2:8-2:10 Unexpected character "\\" (U+005c). 4 | Stopping due to compile errors. 5 | -------------------------------------------------------------------------------- /test/unit/crow-parser/line-continuation.crow: -------------------------------------------------------------------------------- 1 | \ 2 | # comment 3 | dummy-line-continuation nat() 4 | 0 5 | 6 | main void() 7 | x = 8 | "a" ~~ 9 | "b" 10 | y = x repeat \ 11 | 2 12 | y is \ 13 | "abab" 14 | -------------------------------------------------------------------------------- /test/unit/crow-parser/pointers.crow: -------------------------------------------------------------------------------- 1 | dummy-pointers nat() 2 | 0 3 | 4 | test trusted, native extern 5 | r mut r = 0, 6 | rp r mut* = &r 7 | rp->x := 3 8 | r.x is 3 9 | 10 | -r record(x mut nat) by-val, mut 11 | -------------------------------------------------------------------------------- /test/unit/variants.crow: -------------------------------------------------------------------------------- 1 | dummy-variants nat() 2 | 0 3 | 4 | test 5 | a v = 1 m 6 | a.m!.x is 1 7 | assert a.n is-empty 8 | 9 | -v variant 10 | -m record(x nat) v variant-member 11 | -n record v variant-member 12 | -------------------------------------------------------------------------------- /test/end-to-end/compile-errors/extern-warnings.crow: -------------------------------------------------------------------------------- 1 | main void() 2 | () 3 | 4 | f void() bare, libc extern 5 | 6 | f void() unsafe, libc extern 7 | 8 | f void() summon, libc extern 9 | 10 | f void() pure 11 | () 12 | -------------------------------------------------------------------------------- /test/end-to-end/compile-errors/main-duplicate.crow.out: -------------------------------------------------------------------------------- 1 | exit code: 1 2 | stderr: 3 | test/end-to-end/compile-errors/main-duplicate.crow 4:1-5:7 Module contains multiple valid 'main' functions. 4 | Stopping due to compile errors. 5 | -------------------------------------------------------------------------------- /test/end-to-end/compile-errors/type-param-cant-have-type-args.crow.out: -------------------------------------------------------------------------------- 1 | exit code: 0 2 | stderr: 3 | test/end-to-end/compile-errors/type-param-cant-have-type-args.crow 4:17-4:18 Can't provide type arguments to a type parameter. 4 | -------------------------------------------------------------------------------- /test/unit/library/symbol-tests.crow: -------------------------------------------------------------------------------- 1 | dummy-symbol-tests nat64() 2 | 0 3 | 4 | test 5 | cat string = "foo" ~~ "bar" 6 | cat is "foobar" 7 | sym symbol = cat to 8 | sym is "foobar" 9 | sym.to::string is "foobar" 10 | -------------------------------------------------------------------------------- /demo/hello.crow: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env crow 2 | import 3 | crow/io/print: out, print 4 | 5 | main nat(args string[]) summon 6 | out print if args is-empty 7 | "Hello, world!" 8 | else 9 | "Hello, {" " join args}!" 10 | 0 11 | -------------------------------------------------------------------------------- /test/end-to-end/compile-errors/builtin-does-not-exist.crow: -------------------------------------------------------------------------------- 1 | main void() 2 | () 3 | 4 | x builtin 5 | 6 | x spec builtin 7 | 8 | # There are '==' builtins but not with this signature 9 | == string(a nat, b int) builtin 10 | -------------------------------------------------------------------------------- /test/end-to-end/compile-errors/destructure-errors.crow: -------------------------------------------------------------------------------- 1 | main void() 2 | p (nat, string) = 1, "one" 3 | 4 | x0, y0 string = p 5 | x1 bool, y1 = p 6 | x2 bool, y2 symbol = p 7 | 8 | x3, y3, z3 = p 9 | x4, y4 = 42::nat 10 | -------------------------------------------------------------------------------- /test/end-to-end/compile-errors/duplicate-import.crow.out: -------------------------------------------------------------------------------- 1 | exit code: 0 2 | stdout: 3 | info: 3.141592653589794 4 | stderr: 5 | test/end-to-end/compile-errors/duplicate-import.crow 2:25-2:27 'pi' is imported twice from the same module. 6 | -------------------------------------------------------------------------------- /test/unit/options.crow: -------------------------------------------------------------------------------- 1 | dummy-options nat() 2 | 0 3 | 4 | test 5 | a nat? = () 6 | b nat? = 1, 7 | c nat? = 2, 8 | 9 | (a ?? 2) is 2 10 | (b ?? 2) is 1 11 | 12 | (a || b) is b 13 | (b || a) is b 14 | (b || c) is b 15 | -------------------------------------------------------------------------------- /test/end-to-end/compile-errors/auto-fun-spec-from-wrong-module.crow.out: -------------------------------------------------------------------------------- 1 | exit code: 0 2 | stderr: 3 | test/end-to-end/compile-errors/auto-fun-spec-from-wrong-module.crow 13:1-13:3 Spec for automatic function comes from unexpected module. 4 | -------------------------------------------------------------------------------- /test/end-to-end/compile-errors/function-pointer-not-bare.crow: -------------------------------------------------------------------------------- 1 | main void() 2 | f void function() = &foo 3 | f[] 4 | 5 | in-js void() js extern 6 | f void function() = &foo 7 | f[] 8 | 9 | foo void() 10 | info log "in foo" 11 | -------------------------------------------------------------------------------- /test/end-to-end/compile-errors/spec-decl-recursion.crow.out: -------------------------------------------------------------------------------- 1 | exit code: 0 2 | stderr: 3 | test/end-to-end/compile-errors/spec-decl-recursion.crow 4:1-4:9 Spec's parents tree is too deep. 4 | Trace: 'b', 'a', 'b', 'a', 'b', 'a', 'b', 'a' 5 | -------------------------------------------------------------------------------- /test/end-to-end/parse-errors/type-mut.crow.out: -------------------------------------------------------------------------------- 1 | exit code: 1 2 | stderr: 3 | test/end-to-end/parse-errors/type-mut.crow 2:11-2:14 To make something mutable, put 'mut' after its name, not after its type. 4 | Stopping due to compile errors. 5 | -------------------------------------------------------------------------------- /test/end-to-end/compile-errors/bogus-local.crow.out: -------------------------------------------------------------------------------- 1 | exit code: 1 2 | stderr: 3 | test/end-to-end/compile-errors/bogus-local.crow 2:9-2:10 There is no function or variable named 'z'. 4 | Uncaught exception: Reached compile error 5 | at main 6 | -------------------------------------------------------------------------------- /test/end-to-end/compile-errors/cant-import-crow-as-string.crow.out: -------------------------------------------------------------------------------- 1 | exit code: 1 2 | stderr: 3 | test/end-to-end/compile-errors/cant-import-crow-as-string.crow 2:5-2:32 Can't import a '.crow' file as content. 4 | Stopping due to compile errors. 5 | -------------------------------------------------------------------------------- /test/end-to-end/parse-errors/interpolated-string-literal-bad-position.crow.out: -------------------------------------------------------------------------------- 1 | exit code: 1 2 | stderr: 3 | test/end-to-end/parse-errors/interpolated-string-literal-bad-position.crow 2:18-2:19 Expected '}'. 4 | Stopping due to compile errors. 5 | -------------------------------------------------------------------------------- /test/end-to-end/compile-errors/extern-redundant.crow: -------------------------------------------------------------------------------- 1 | main void() trusted 2 | info log if extern linux 3 | if extern linux 4 | "a" 5 | else 6 | "b" 7 | else 8 | # Using the same value to keep test output consistent 9 | "a" 10 | -------------------------------------------------------------------------------- /test/end-to-end/compile-errors/extern-redundant.crow.out: -------------------------------------------------------------------------------- 1 | exit code: 0 2 | stdout: 3 | info: a 4 | stderr: 5 | test/end-to-end/compile-errors/extern-redundant.crow 3:19-3:24 Extern 'linux' is already in scope, so this expression is always 'true'. 6 | -------------------------------------------------------------------------------- /test/end-to-end/compile-errors/match-variant-without-else.crow.out: -------------------------------------------------------------------------------- 1 | exit code: 0 2 | stdout: 3 | info: hello 4 | stderr: 5 | test/end-to-end/compile-errors/match-variant-without-else.crow 2:14-2:19 Match on a 'variant' must have an explicit 'else'. 6 | -------------------------------------------------------------------------------- /test/end-to-end/compile-errors/set-field-of-by-val.crow.out: -------------------------------------------------------------------------------- 1 | exit code: 1 2 | stderr: 3 | test/end-to-end/compile-errors/set-field-of-by-val.crow 3:9-3:11 There is no function named 'set-x'. 4 | Uncaught exception: Reached compile error 5 | at main 6 | -------------------------------------------------------------------------------- /test/end-to-end/compile-errors/variant-member-purity.crow.out: -------------------------------------------------------------------------------- 1 | exit code: 0 2 | stdout: 3 | info: done 4 | stderr: 5 | test/end-to-end/compile-errors/variant-member-purity.crow 5:15-5:31 Variant 'v' has purity 'data', but member 'm' has purity 'mut'. 6 | -------------------------------------------------------------------------------- /test/end-to-end/compile-errors/variant-member-template.crow.out: -------------------------------------------------------------------------------- 1 | exit code: 0 2 | stdout: 3 | info: done 4 | stderr: 5 | test/end-to-end/compile-errors/variant-member-template.crow 5:23-5:39 'x' can't be a 'variant-member' because it is a template. 6 | -------------------------------------------------------------------------------- /test/end-to-end/compile-errors/variant-member-wrong-type-arg.crow.out: -------------------------------------------------------------------------------- 1 | exit code: 0 2 | stdout: 3 | info: bar 4 | stderr: 5 | test/end-to-end/compile-errors/variant-member-wrong-type-arg.crow 3:8-3:11 Type 'foo' is not a member of variant 'nat64 v'. 6 | -------------------------------------------------------------------------------- /test/unit/library/shared-array-tests.crow: -------------------------------------------------------------------------------- 1 | dummy-shared-array-tests nat() 2 | 0 3 | 4 | test 5 | res nat shared[] = () 6 | for x : 0::nat .. 100 parallel 7 | res ~= x 8 | () 9 | res.move-to::nat[].sort is (0 .. 100).to 10 | () 11 | -------------------------------------------------------------------------------- /demo/libraries/sndfile/util.crow: -------------------------------------------------------------------------------- 1 | import 2 | crow/c-types: c-int 3 | ./headers: sf_error_number 4 | 5 | +check-sndfile-error void(err c-int) unsafe, (native, sndfile) extern 6 | assert err == 0 : "libsndfile error {err}: {err sf_error_number}" error 7 | -------------------------------------------------------------------------------- /demo/stdin.crow: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env crow 2 | import 3 | crow/io/print: out, print 4 | crow/io/stdin: read-stdin 5 | 6 | main void() summon, native extern 7 | out print "What's your name?" 8 | name = read-stdin 9 | out print "Hello, {name}" 10 | -------------------------------------------------------------------------------- /test/end-to-end/compile-errors/import-non-utf8-as-string.crow.out: -------------------------------------------------------------------------------- 1 | exit code: 1 2 | stderr: 3 | test/end-to-end/compile-errors/import-non-utf8-as-string.crow 2:5-2:31 File is not encoded as UTF-8 or has encoding errors. 4 | Stopping due to compile errors. 5 | -------------------------------------------------------------------------------- /test/end-to-end/compile-errors/string-js-any.crow.out: -------------------------------------------------------------------------------- 1 | exit code: 1 2 | stderr: 3 | test/end-to-end/compile-errors/string-js-any.crow 5:16-5:21 Cant' create a 'js-any' value without 'js extern'. 4 | Uncaught exception: Reached compile error 5 | at main 6 | -------------------------------------------------------------------------------- /test/unit/crow-parser/comments.crow: -------------------------------------------------------------------------------- 1 | dummy-comments nat() 2 | 0 3 | 4 | test 5 | x string = 6 | ### 7 | comment 8 | ### 9 | "hello" 10 | ### 11 | ### 12 | x is "hello" 13 | 14 | ### 15 | comment at end of file (no newline after) 16 | ### -------------------------------------------------------------------------------- /test/end-to-end/compile-errors/fun-pointer-not-found.crow.out: -------------------------------------------------------------------------------- 1 | exit code: 1 2 | stderr: 3 | test/end-to-end/compile-errors/fun-pointer-not-found.crow 2:26-2:29 Could not find a function 'foo void()'. 4 | Uncaught exception: Reached compile error 5 | at main 6 | -------------------------------------------------------------------------------- /test/end-to-end/compile-errors/function-pointer-not-bare.crow.out: -------------------------------------------------------------------------------- 1 | exit code: 0 2 | stdout: 3 | info: in foo 4 | stderr: 5 | test/end-to-end/compile-errors/function-pointer-not-bare.crow 2:25-2:29 The target of a function pointer must be a 'bare' function. 6 | -------------------------------------------------------------------------------- /test/end-to-end/compile-errors/variant-method-missing.crow: -------------------------------------------------------------------------------- 1 | main void() 2 | info log x.foo 3 | info log y.foo 4 | () 5 | 6 | v variant 7 | foo string() 8 | x record v variant-member 9 | foo string(_ x) 10 | "x" 11 | y record v variant-member 12 | -------------------------------------------------------------------------------- /test/unit/type-cyclic-reference.crow: -------------------------------------------------------------------------------- 1 | dummy-type-cyclic-reference nat() 2 | 0 3 | 4 | test 5 | a r = 1, () 6 | b r = 2, (a,) 7 | assert a.next is-empty 8 | b.next!.value is 1 9 | assert b.next!.next is-empty 10 | -r record(value nat, next r?) 11 | -------------------------------------------------------------------------------- /test/end-to-end/compile-errors/auto-fun-spec-from-wrong-module.crow: -------------------------------------------------------------------------------- 1 | no-std 2 | import 3 | crow/bool: bool 4 | crow/misc: new, void 5 | 6 | main void() 7 | () 8 | 9 | equal[t] spec 10 | == bool(a t, b t) 11 | 12 | r record 13 | == bool(a r, b r) 14 | -------------------------------------------------------------------------------- /test/end-to-end/compile-errors/main-missing.crow.out: -------------------------------------------------------------------------------- 1 | exit code: 1 2 | stderr: 3 | test/end-to-end/compile-errors/main-missing.crow 1:1-1:1 Module should have a function: 4 | main void() 5 | Or: 6 | main nat64(args string[]) 7 | Stopping due to compile errors. 8 | -------------------------------------------------------------------------------- /test/end-to-end/compile-errors/spec-errors.crow.out: -------------------------------------------------------------------------------- 1 | exit code: 0 2 | stderr: 3 | test/end-to-end/compile-errors/spec-errors.crow 4:8-4:14 A spec can't be 'by-val'. 4 | test/end-to-end/compile-errors/spec-errors.crow 5:14-5:26 A spec signature can't be variadic. 5 | -------------------------------------------------------------------------------- /test/end-to-end/compile-errors/spec-inst-recursion.crow: -------------------------------------------------------------------------------- 1 | main void() 2 | ""::string foo 3 | 4 | foo[t] spec 5 | foo void(a t) 6 | 7 | bar[t] spec 8 | bar void(a t) 9 | 10 | foo[t] void(_ t) t bar 11 | () 12 | 13 | bar[t] void(_ t) t foo 14 | () 15 | -------------------------------------------------------------------------------- /test/end-to-end/compile-errors/spec-multiple-impls.crow: -------------------------------------------------------------------------------- 1 | # Redundant function 2 | to json(a string) 3 | a string 4 | 5 | to-json-string[t] string(a t) (json, t) to 6 | a.to::json show 7 | 8 | main void() 9 | info log ("a",)::string[] to-json-string 10 | -------------------------------------------------------------------------------- /test/end-to-end/compile-errors/shared-lambda-errors.crow: -------------------------------------------------------------------------------- 1 | 2 | main void() 3 | not-lambda nat = shared 0 4 | not-shared nat mut() = shared () => 0 5 | mut-param void shared(p nat mut[]) = shared x => () 6 | mut-return nat mut[] shared() = shared () => () 7 | () 8 | -------------------------------------------------------------------------------- /test/end-to-end/compile-errors/spec-use-invalid.crow: -------------------------------------------------------------------------------- 1 | main void() 2 | () 3 | 4 | nat64[t] builtin t equal 5 | 6 | e[t] enum(x) t equal 7 | 8 | ex[t] extern t equal 9 | 10 | f[t] flags t equal 11 | 12 | r[t] record t equal 13 | 14 | u[t] union(x) t equal 15 | -------------------------------------------------------------------------------- /test/end-to-end/compile-errors/variant-multiple-members-with-name.crow: -------------------------------------------------------------------------------- 1 | main void() 2 | a v = x 3 | info log match a 4 | as x 5 | "x" 6 | else 7 | "something else" 8 | () 9 | 10 | v variant 11 | x record v variant-member 12 | x record v variant-member 13 | -------------------------------------------------------------------------------- /test/end-to-end/parse-errors/import-missing-name.crow.out: -------------------------------------------------------------------------------- 1 | exit code: 1 2 | stderr: 3 | test/end-to-end/parse-errors/import-missing-name.crow 2:5-2:6 Library 'x' is not configured. 4 | It must be added to "include" in 'crow-config.json'. 5 | Stopping due to compile errors. 6 | -------------------------------------------------------------------------------- /demo/sound/crow-config.json: -------------------------------------------------------------------------------- 1 | { 2 | "include": { 3 | "audio": "../libraries/audio", 4 | "SDL2": "../libraries/SDL2", 5 | "sndfile": "../libraries/sndfile", 6 | }, 7 | "extern": { 8 | "SDL2": "../extern/SDL2", 9 | "sndfile": "../extern/sndfile" 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /test/end-to-end/compile-errors/match-case-missing-name.crow.out: -------------------------------------------------------------------------------- 1 | exit code: 1 2 | stderr: 3 | test/end-to-end/compile-errors/match-case-missing-name.crow 3:7-3:7 A branch of a 'match' must be an identifier, number literal, or string literal. 4 | Stopping due to compile errors. 5 | -------------------------------------------------------------------------------- /test/unit/file-import.crow: -------------------------------------------------------------------------------- 1 | import 2 | ../../editor/vscode/license.txt as license string 3 | ../../editor/vscode/license.txt as bytes nat8 array 4 | 5 | dummy-file-import nat() 6 | 0 7 | 8 | test 9 | license is "public domain" 10 | bytes is "public domain".to-bytes 11 | -------------------------------------------------------------------------------- /test/end-to-end/compile-errors/variant-member-wrong-type-arg.crow: -------------------------------------------------------------------------------- 1 | main void() 2 | info log match bar 3 | as foo 4 | x 5 | as bar 6 | "bar" 7 | else 8 | "other" 9 | 10 | v[t] variant 11 | 12 | foo record string v variant-member 13 | bar record nat v variant-member 14 | -------------------------------------------------------------------------------- /test/end-to-end/compile-errors/library-not-configured.crow.out: -------------------------------------------------------------------------------- 1 | exit code: 1 2 | stderr: 3 | test/end-to-end/compile-errors/library-not-configured.crow 2:5-2:17 Library 'non-existent' is not configured. 4 | It must be added to "include" in 'crow-config.json'. 5 | Stopping due to compile errors. 6 | -------------------------------------------------------------------------------- /test/end-to-end/compile-errors/pointer-expression-failed-inference.crow.out: -------------------------------------------------------------------------------- 1 | exit code: 1 2 | stderr: 3 | test/end-to-end/compile-errors/pointer-expression-failed-inference.crow 3:16-3:18 'pointer' expression needs an expected type. 4 | Uncaught exception: Reached compile error 5 | at main 6 | -------------------------------------------------------------------------------- /include/crow/crypto/private/sodium.crow: -------------------------------------------------------------------------------- 1 | import 2 | system/sodium: sodium_init 3 | ../../private/thread-utils: global-lock, with-lock 4 | 5 | ensure-sodium-initialized void() trusted, (native, sodium) extern 6 | global-lock with-lock () => 7 | err = sodium_init 8 | assert err == 0 || err == 1 9 | -------------------------------------------------------------------------------- /test/end-to-end/compile-errors/variant-method-missing.crow.out: -------------------------------------------------------------------------------- 1 | exit code: 1 2 | stdout: 3 | info: x 4 | stderr: 5 | test/end-to-end/compile-errors/variant-method-missing.crow 11:10-11:26 Could not find a function 'foo string(_ y)'. 6 | Uncaught exception: Reached compile error 7 | at foo 8 | at main 9 | -------------------------------------------------------------------------------- /test/unit/by-val-or-ref.crow: -------------------------------------------------------------------------------- 1 | dummy-by-val-or-ref nat() 2 | 0 3 | 4 | test trusted, native extern 5 | size-of@bv is 24 6 | size-of@br is 8 7 | size-of@unspecified is 16 8 | -bv record(x bv*, y nat, z nat) by-val 9 | -br record(x nat, y nat) by-ref 10 | -unspecified record(x nat, y nat) 11 | -------------------------------------------------------------------------------- /site-src/play.html: -------------------------------------------------------------------------------- 1 |
2 |

3 | Edit the text, then click the button to run it. 4 | The only I/O supported is logging. 5 |

6 | 7 | 8 | main void() 9 | info log "Hello, world!" 10 | 11 |
12 | -------------------------------------------------------------------------------- /test/end-to-end/compile-errors/function-pointer-lambda.crow.out: -------------------------------------------------------------------------------- 1 | exit code: 1 2 | stderr: 3 | test/end-to-end/compile-errors/function-pointer-lambda.crow 2:25-2:33 A function pointer can't be implemented by a lambda. Write a function and use '&f' instead. 4 | Uncaught exception: Reached compile error 5 | at main 6 | -------------------------------------------------------------------------------- /test/end-to-end/compile-errors/imported-name-refers-to-nothing.crow.out: -------------------------------------------------------------------------------- 1 | exit code: 1 2 | stdout: 3 | info: hello 4 | stderr: 5 | test/end-to-end/compile-errors/imported-name-refers-to-nothing.crow 2:17-2:20 Imported name 'foo' does not refer to anything. 6 | Uncaught exception: Reached compile error 7 | at main 8 | -------------------------------------------------------------------------------- /test/end-to-end/parse-errors/type-parens.crow.out: -------------------------------------------------------------------------------- 1 | exit code: 1 2 | stderr: 3 | test/end-to-end/parse-errors/type-parens.crow 1:10-1:12 '()' is not a type. Did you mean 'void'? 4 | test/end-to-end/parse-errors/type-parens.crow 2:10-2:12 '()' is not a type. Did you mean 'void'? 5 | Stopping due to compile errors. 6 | -------------------------------------------------------------------------------- /test/end-to-end/compile-errors/enum-value-overflow.crow: -------------------------------------------------------------------------------- 1 | main void() 2 | () 3 | 4 | e enum 5 | a = -1 6 | b = 0 7 | c = 4294967295 8 | d = 4294967296 9 | 10 | e enum int8 storage 11 | a = -129 12 | b = -128 13 | c = 127 14 | d = 128 15 | 16 | f flags nat16 storage 17 | a = 65535 18 | b = 65536 19 | -------------------------------------------------------------------------------- /test/end-to-end/compile-errors/match-warnings.crow: -------------------------------------------------------------------------------- 1 | main void() 2 | () 3 | 4 | f nat(a nat?) 5 | match a 6 | as none 7 | 1 8 | as some x 9 | x 10 | else 11 | 3 12 | 13 | f nat(a comparison) 14 | match a 15 | as less 16 | 1 17 | as equal 18 | 2 19 | as greater 20 | 3 21 | else 22 | 4 23 | -------------------------------------------------------------------------------- /test/end-to-end/compile-errors/match-warnings.crow.out: -------------------------------------------------------------------------------- 1 | exit code: 0 2 | stderr: 3 | test/end-to-end/compile-errors/match-warnings.crow 10:5-10:9 'match' handles every case, so the 'else' is unused. 4 | test/end-to-end/compile-errors/match-warnings.crow 21:5-21:9 'match' handles every case, so the 'else' is unused. 5 | -------------------------------------------------------------------------------- /test/end-to-end/parse-errors/spec-signature-unfinished.crow.out: -------------------------------------------------------------------------------- 1 | exit code: 1 2 | stderr: 3 | test/end-to-end/parse-errors/spec-signature-unfinished.crow 3:1-2:12 Expected a name (non-operator). 4 | test/end-to-end/parse-errors/spec-signature-unfinished.crow 3:1-2:12 Expected ','. 5 | Stopping due to compile errors. 6 | -------------------------------------------------------------------------------- /test/unit/library/shared-map-tests.crow: -------------------------------------------------------------------------------- 1 | dummy-shared-map-tests nat() 2 | 0 3 | 4 | test 5 | res nat shared[nat] = () 6 | for x : 0::nat .. 100 parallel 7 | res[x] := x * 2 8 | () 9 | res.move-to::nat[nat] is for x : 0::nat .. 100 10 | x, x * 2 11 | () 12 | 13 | -to symbol(a nat) 14 | a.show to 15 | -------------------------------------------------------------------------------- /test/end-to-end/compile-errors/auto-fun-flags.crow: -------------------------------------------------------------------------------- 1 | main void() 2 | x r = 1, (), () 3 | info log "{x == x}" 4 | () 5 | 6 | r record 7 | x nat 8 | y foo 9 | z bar 10 | == bool(a r, b r) bare 11 | 12 | foo record 13 | == bool(a foo, b foo) unsafe 14 | 15 | bar record 16 | == bool(a bar, b bar) summon 17 | 18 | -------------------------------------------------------------------------------- /test/end-to-end/compile-errors/lambda-errors.crow: -------------------------------------------------------------------------------- 1 | main void() 2 | d = () => 1 3 | 3 foo (x string) => () 4 | 3 bar x => () 5 | 6 | foo void(x nat, f void mut(x nat)) 7 | () 8 | bar void(x nat, f void mut(x nat)) 9 | () 10 | bar void(x nat, f nat) 11 | () 12 | bar void(x nat, f void mut(x string)) 13 | () 14 | -------------------------------------------------------------------------------- /test/end-to-end/compile-errors/record-privacy-b.crow: -------------------------------------------------------------------------------- 1 | import 2 | ./record-privacy-a 3 | 4 | main void() 5 | () 6 | 7 | foo void() 8 | a private-ctor = 0, 9 | _ = a 10 | b private-mut = 0, 0, 0 11 | b.j := 0 12 | _ = b.j 13 | b.k := 0 14 | _ = b.k 15 | b.l := 0 16 | _ = b.l 17 | _ internal-ctor = 0, 18 | -------------------------------------------------------------------------------- /test/end-to-end/parse-errors/unfinished-string-interpolation.crow.out: -------------------------------------------------------------------------------- 1 | exit code: 1 2 | stderr: 3 | test/end-to-end/parse-errors/unfinished-string-interpolation.crow 2:7-2:7 Unexpected newline. 4 | test/end-to-end/parse-errors/unfinished-string-interpolation.crow 2:7-2:7 Expected '}'. 5 | Stopping due to compile errors. 6 | -------------------------------------------------------------------------------- /test/unit/loops.crow: -------------------------------------------------------------------------------- 1 | dummy-loops nat() 2 | 0 3 | 4 | test 5 | x mut nat = 0 6 | y nat = loop 7 | if x == 5 8 | break x * 2 9 | else 10 | x +:= 1 11 | continue 12 | x is 5 13 | y is 10 14 | 15 | until x == 15 16 | x +:= 1 17 | x is 15 18 | 19 | while x > 10 20 | x -:= 1 21 | x is 10 22 | -------------------------------------------------------------------------------- /test/end-to-end/compile-errors/cant-infer-type-args.crow.out: -------------------------------------------------------------------------------- 1 | exit code: 1 2 | stderr: 3 | test/end-to-end/compile-errors/cant-infer-type-args.crow 5:5-5:6 Can't infer type arguments to 'f[t] void()' (from test/end-to-end/compile-errors/cant-infer-type-args.crow line 1) 4 | Uncaught exception: Reached compile error 5 | at main 6 | -------------------------------------------------------------------------------- /test/end-to-end/compile-errors/mut-param.crow.out: -------------------------------------------------------------------------------- 1 | exit code: 1 2 | stderr: 3 | test/end-to-end/compile-errors/mut-param.crow 6:10-6:13 A parameter can't be mutable. 4 | test/end-to-end/compile-errors/mut-param.crow 7:5-7:12 Local variable 'a' was not marked 'mut'. 5 | Uncaught exception: Reached compile error 6 | at f 7 | at main 8 | -------------------------------------------------------------------------------- /test/unit/crow-parser/operator-precedence.crow: -------------------------------------------------------------------------------- 1 | dummy-operator-precedence nat() 2 | 0 3 | 4 | test 5 | xs nat mut[] = () 6 | a nat mut[]? = xs, 7 | a ?? () foo= 3 8 | xs.move-to::nat[] is (3,) 9 | 10 | foo= void(a nat mut[], b nat) 11 | a ~= b 12 | 13 | test 14 | (1::nat64) * 2 + 3 is 5 15 | 1::nat64 + 2 * 3 is 7 16 | -------------------------------------------------------------------------------- /test/end-to-end/compile-errors/literal-does-not-match-expected-type.crow.out: -------------------------------------------------------------------------------- 1 | exit code: 1 2 | stderr: 3 | test/end-to-end/compile-errors/literal-does-not-match-expected-type.crow 2:16-2:17 The literal doesn't match the expected type at this location. 4 | Expected type 'string'. 5 | Uncaught exception: Reached compile error 6 | at main 7 | -------------------------------------------------------------------------------- /demo/libraries/SDL2/SDL_rwops.crow: -------------------------------------------------------------------------------- 1 | import 2 | crow/c-types: c-int 3 | 4 | +SDL_RWops extern 5 | 6 | +SDL_RWFromFile SDL_RWops mut*(file c-string, mode c-string) SDL2 extern 7 | +SDL_RWFromMem SDL_RWops mut*(mem any-mut-pointer, size c-int) SDL2 extern 8 | +SDL_RWFromConstMem SDL_RWops mut*(mem any-const-pointer, size c-int) SDL2 extern 9 | -------------------------------------------------------------------------------- /test/end-to-end/compile-errors/string-literal-invalid.crow.out: -------------------------------------------------------------------------------- 1 | exit code: 0 2 | stdout: 3 | info: a 4 | info: a 5 | stderr: 6 | test/end-to-end/compile-errors/string-literal-invalid.crow 2:14-2:20 'string' literal can't contain '\0'. 7 | test/end-to-end/compile-errors/string-literal-invalid.crow 3:16-3:22 'symbol' literal can't contain '\0'. 8 | -------------------------------------------------------------------------------- /test/end-to-end/runnable/logging.crow: -------------------------------------------------------------------------------- 1 | main void() native extern 2 | info log "Logged once" 3 | lh = get-log-handler 4 | doubler log-handler = logged => 5 | lh[logged] 6 | lh[logged] 7 | with : doubler temp-log-handler 8 | warn log "Logged twice" 9 | with : (_ => ()) temp-log-handler 10 | warn log "Logged never" 11 | () 12 | -------------------------------------------------------------------------------- /test/unit/matches.crow: -------------------------------------------------------------------------------- 1 | dummy-matches nat() 2 | 0 3 | 4 | # Test that switching on a signed int < 64 bits works 5 | test trusted, native extern 6 | # Read a pointer to get an int32 that is not sign extended 7 | a int32 = -7 8 | ap int32* = &a 9 | b = *ap 10 | match b 11 | as -7 12 | () 13 | else 14 | throw unreachable 15 | -------------------------------------------------------------------------------- /test/end-to-end/compile-errors/wrong-number-type-args.crow.out: -------------------------------------------------------------------------------- 1 | exit code: 0 2 | stderr: 3 | test/end-to-end/compile-errors/wrong-number-type-args.crow 8:7-8:12 There are functions named 'magic', but none takes 1 type arguments. candidates: 4 | 'magic[out, in] out?(a in?)' (from test/end-to-end/compile-errors/wrong-number-type-args.crow line 4) 5 | -------------------------------------------------------------------------------- /include/system/stdlib.crow: -------------------------------------------------------------------------------- 1 | no-std 2 | import 3 | crow/c-types: size_t 4 | crow/pointer: any-mut-pointer 5 | crow/private/bootstrap: void 6 | 7 | +calloc any-mut-pointer(n-elems size_t, sizeof-elem size_t) libc extern, pure 8 | +malloc any-mut-pointer(size-bytes size_t) libc extern, pure 9 | +free void(p any-mut-pointer) libc extern, pure 10 | -------------------------------------------------------------------------------- /test/end-to-end/compile-errors/trusted-unnecessary.crow: -------------------------------------------------------------------------------- 1 | main void() 2 | () 3 | 4 | f nat*() unsafe, native extern 5 | trusted null 6 | 7 | f nat*() native extern 8 | trusted trusted null 9 | 10 | f nat() native extern 11 | # testing twice to verify that we reset 'usedTrusted' after each 'trusted' 12 | _ nat = trusted 0 13 | trusted 0 14 | -------------------------------------------------------------------------------- /test/end-to-end/compile-errors/import-non-existing.crow.out: -------------------------------------------------------------------------------- 1 | exit code: 1 2 | stderr: 3 | test/end-to-end/compile-errors/does-not-exist.crow 1:1-1:1 This file does not exist. 4 | test/end-to-end/compile-errors/import-non-existing.crow 2:5-2:21 Imported file test/end-to-end/compile-errors/does-not-exist.crow does not exist. 5 | Stopping due to compile errors. 6 | -------------------------------------------------------------------------------- /test/failure.crow: -------------------------------------------------------------------------------- 1 | failure record(path string, message string) 2 | 3 | show-failures string(failures failure[]) 4 | s string = "\n" join for failure : failures 5 | "{bold}{failure.path}{reset} {failure.message}" 6 | "{s}\n{failures.size} failures" 7 | 8 | # TODO:MOVE 9 | -bold string() 10 | "\x1b[1m" 11 | 12 | -reset string() 13 | "\x1b[m" 14 | -------------------------------------------------------------------------------- /test/end-to-end/compile-errors/loop-disallowed-body.crow.out: -------------------------------------------------------------------------------- 1 | exit code: 1 2 | stderr: 3 | test/end-to-end/compile-errors/loop-disallowed-body.crow 3:9-3:12 Loop body cannot be a 'finally' expression 4 | test/end-to-end/compile-errors/loop-disallowed-body.crow 9:9-9:16 Loop body cannot be a 'finally' expression 5 | Uncaught exception: Reached compile error 6 | at main 7 | -------------------------------------------------------------------------------- /test/end-to-end/compile-errors/tuple-too-big.crow.out: -------------------------------------------------------------------------------- 1 | exit code: 1 2 | stderr: 3 | test/end-to-end/compile-errors/tuple-too-big.crow 2:5-2:44 Expected a tuple with 10 elements, but got '<>'. 4 | test/end-to-end/compile-errors/tuple-too-big.crow 5:4-5:52 This tuple has 10 elements; the maximum allowed is 9 5 | Uncaught exception: Reached compile error 6 | at main 7 | -------------------------------------------------------------------------------- /test/end-to-end/compile-errors/variant-member-of-non-variant.crow.out: -------------------------------------------------------------------------------- 1 | exit code: 1 2 | stderr: 3 | test/end-to-end/compile-errors/variant-member-of-non-variant.crow 2:14-2:15 There is no function or variable named 'm'. 4 | test/end-to-end/compile-errors/variant-member-of-non-variant.crow 4:10-4:29 Not a variant: bool 5 | Uncaught exception: Reached compile error 6 | at main 7 | -------------------------------------------------------------------------------- /test/end-to-end/compile-errors/variant-method-impl-visibility.crow.out: -------------------------------------------------------------------------------- 1 | exit code: 0 2 | stdout: 3 | info: x 4 | stderr: 5 | test/end-to-end/compile-errors/variant-method-impl-visibility.crow 6:10-6:26 A method of variant 'v' is implemented by 'foo string(_ x)' (from test/end-to-end/compile-errors/variant-method-impl-visibility.crow line 7), but it is less visible than 'x'. 6 | -------------------------------------------------------------------------------- /test/end-to-end/parse-errors/import-file-missing-type.crow.out: -------------------------------------------------------------------------------- 1 | exit code: 1 2 | stderr: 3 | test/end-to-end/parse-errors/import-file-missing-type.crow 2:20-2:20 Unexpected newline. 4 | test/end-to-end/parse-errors/import-file-missing-type.crow 2:20-2:20 Import file type not allowed; the only supported types are 'nat8 array' and 'string'. 5 | Stopping due to compile errors. 6 | -------------------------------------------------------------------------------- /test/end-to-end/compile-errors/function-missing-body.crow.out: -------------------------------------------------------------------------------- 1 | exit code: 1 2 | stderr: 3 | test/end-to-end/compile-errors/function-missing-body.crow 1:1-1:5 Function needs a body. (An automatic function must be named '==', '<=>', or 'to'.) 4 | test/end-to-end/compile-errors/function-missing-body.crow 2:1-2:5 This test needs a body. 5 | Uncaught exception: Reached compile error 6 | at main 7 | -------------------------------------------------------------------------------- /test/end-to-end/compile-errors/function-pointer-not-supported.crow: -------------------------------------------------------------------------------- 1 | main void() 2 | f void function() = &foo 3 | g void function() = &goo 4 | h void function() = &(1 + 1) 5 | 6 | hoo[t] spec 7 | hoo void(a t) 8 | 9 | use-spec[t] void(x t) t hoo 10 | f void function(x t) = &hoo 11 | f[x] 12 | 13 | foo void() 14 | () 15 | foo void() 16 | () 17 | 18 | goo[t] void() 19 | () 20 | -------------------------------------------------------------------------------- /test/end-to-end/parse-errors/type-bracket-unclosed.crow.out: -------------------------------------------------------------------------------- 1 | exit code: 1 2 | stderr: 3 | test/end-to-end/parse-errors/type-bracket-unclosed.crow 1:7-1:9 '()' is not a type. Did you mean 'void'? 4 | test/end-to-end/parse-errors/type-bracket-unclosed.crow 1:9-1:9 Expected ']'. 5 | test/end-to-end/parse-errors/type-bracket-unclosed.crow 1:9-1:9 Expected '('. 6 | Stopping due to compile errors. 7 | -------------------------------------------------------------------------------- /test/end-to-end/compile-errors/empty-enum-or-union.crow.out: -------------------------------------------------------------------------------- 1 | exit code: 1 2 | stderr: 3 | test/end-to-end/compile-errors/empty-enum-or-union.crow 10:1-10:7 An enum or union type must have at least one member. 4 | test/end-to-end/compile-errors/empty-enum-or-union.crow 12:1-12:8 An enum or union type must have at least one member. 5 | Uncaught exception: Reached compile error 6 | at f 7 | at main 8 | -------------------------------------------------------------------------------- /test/end-to-end/runnable/identifiers.crow.out: -------------------------------------------------------------------------------- 1 | info: crow 2 | info: kráka 3 | info: κοράκι 4 | info: ворона 5 | info: עורב 6 | info: غراب 7 | info: کلاغ 8 | info: کوا 9 | info: কাক 10 | info: कौआ 11 | info: कावळा 12 | info: कऊआ 13 | info: ਕਾਂ 14 | info: કાગડો 15 | info: காகம் 16 | info: కాకి 17 | info: ཁྭ་ཏ་ནག་པོ། 18 | info: quạ 19 | info: からす 20 | info: カラス 21 | info: 乌鸦 22 | info: 까마귀 23 | -------------------------------------------------------------------------------- /src/util/cell.d: -------------------------------------------------------------------------------- 1 | module util.cell; 2 | 3 | @safe @nogc pure nothrow: 4 | 5 | import util.memory : initMemory; 6 | 7 | struct Cell(T) { 8 | private: 9 | union { 10 | T value; 11 | } 12 | } 13 | 14 | @trusted ref inout(T) cellGet(T)(ref inout Cell!T cell) => 15 | cell.value; 16 | 17 | @trusted void cellSet(T)(ref Cell!T cell, T value) { 18 | initMemory(&cell.value, value); 19 | } 20 | -------------------------------------------------------------------------------- /test/end-to-end/compile-errors/pointer-mutability.crow: -------------------------------------------------------------------------------- 1 | main void() unsafe, native extern 2 | r mut r = 1, 2 3 | p r* = &r 4 | mp r mut* = &r 5 | _ nat* = &p->x 6 | _ nat mut* = &p->x 7 | _ nat* = &p->y 8 | _ nat mut* = &p->y 9 | _ nat* = &mp->x 10 | _ nat mut* = &mp->x 11 | _ nat* = &mp->y 12 | _ nat mut* = &mp->y 13 | () 14 | 15 | r record by-val, mut 16 | x nat 17 | y mut nat 18 | -------------------------------------------------------------------------------- /test/end-to-end/parse-errors/string-escape-invalid.crow: -------------------------------------------------------------------------------- 1 | main void() 2 | info log "q is \q" 3 | info log "x is \x" 4 | info log "xit is \xit" 5 | info log "uf00l! is \uf00l!" 6 | info log "d7ff is \ud7ff" # ok 7 | info log "d800 is \ud800" 8 | info log "dfff is \udfff" 9 | info log "e000 is \ue000" # ok 10 | info log "0010ffff is \U0010ffff" # ok 11 | info log "00110000 is \U00110000" 12 | -------------------------------------------------------------------------------- /test/unit/extern-alignment.crow: -------------------------------------------------------------------------------- 1 | dummy-extern-alignment void() 2 | () 3 | 4 | test trusted, native extern 5 | r r = (), (), () 6 | rp r* = &r 7 | ap nat8* = &rp->a 8 | bp nat8* = (&rp->b)::e* pointer-cast 9 | cp nat8* = (&rp->c)::e* pointer-cast 10 | bp - ap is 1 11 | cp - ap is 5 12 | size-of@r is 9 13 | 14 | -r record mut 15 | a nat8 16 | b e 17 | c e 18 | 19 | -e extern(4, 1) 20 | -------------------------------------------------------------------------------- /include/crow/test-util/test-runner.crow: -------------------------------------------------------------------------------- 1 | import 2 | ../io/print: out, print 3 | 4 | # Run every `test` from all source files included in the compilation. 5 | +run-all-tests void() summon 6 | tests = all-tests 7 | out print "Running {tests size} tests" 8 | for x : tests chunked-parallel 0x10 9 | x[] 10 | out print "Done running tests" 11 | () 12 | 13 | -all-tests void function()[]() builtin 14 | -------------------------------------------------------------------------------- /test/end-to-end/compile-errors/assert-or-forbid-warnings.crow.out: -------------------------------------------------------------------------------- 1 | exit code: 0 2 | stderr: 3 | test/end-to-end/compile-errors/assert-or-forbid-warnings.crow 2:19-2:24 The expression after the ':' for an assert or forbid is always thrown; it doesn't need 'throw'. 4 | test/end-to-end/compile-errors/assert-or-forbid-warnings.crow 3:5-3:10 Instead of throwing from a conditional expression, use 'assert' or 'forbid'. 5 | -------------------------------------------------------------------------------- /test/end-to-end/compile-errors/pointer-mutability.crow.out: -------------------------------------------------------------------------------- 1 | exit code: 1 2 | stderr: 3 | test/end-to-end/compile-errors/pointer-mutability.crow 6:18-6:23 Can't get a 'mut' field pointer from a non-'mut' record pointer. 4 | test/end-to-end/compile-errors/pointer-mutability.crow 8:18-8:23 Can't get a 'mut' field pointer from a non-'mut' record pointer. 5 | Uncaught exception: Reached compile error 6 | at main 7 | -------------------------------------------------------------------------------- /test/unit/library/col/array-tests.crow: -------------------------------------------------------------------------------- 1 | dummy-array-tests nat64() 2 | 0 3 | 4 | test 5 | res nat[] = for _ : ((), ())::void[] 6 | 1 7 | res is (1, 1) 8 | 9 | test 10 | res nat[] = for i, _ : ((), ())::void[] with-index 11 | i 12 | res is (0, 1) 13 | 14 | test 15 | a void[] = with out : build 16 | out ~= () 17 | out.size is 1 18 | out ~~= ((), ()) 19 | out.size is 3 20 | a.size is 3 21 | -------------------------------------------------------------------------------- /test/end-to-end/compile-errors/record-privacy-a.crow: -------------------------------------------------------------------------------- 1 | main void() 2 | () 3 | 4 | private-ctor record -new 5 | x nat 6 | 7 | redundant-private record -new 8 | -y nat 9 | 10 | +internal-ctor record ~new 11 | x nat 12 | 13 | redundant-internal record ~new 14 | ~x nat 15 | 16 | +redundant-public record +new 17 | +x nat 18 | 19 | private-mut record mut, +new 20 | -j mut nat 21 | k -mut nat 22 | -l -mut nat 23 | -------------------------------------------------------------------------------- /test/unit/bare-funs.crow: -------------------------------------------------------------------------------- 1 | dummy-bare nat() 2 | 0 3 | 4 | ### 5 | `<` is marked `bare`, but might call a `ctx` function. 6 | In that case, the particular instance of `<` should actually get a ctx. 7 | ### 8 | 9 | test 10 | x t = () 11 | _ = x < x 12 | 13 | t record 14 | 15 | -== bool(_ t, _ t) 16 | false 17 | # This is not marked `bare`, but `<`, which calls it, is. 18 | -<=> comparison(_ t, _ t) 19 | less 20 | -------------------------------------------------------------------------------- /src/test/testSortUtil.d: -------------------------------------------------------------------------------- 1 | module test.testSortUtil; 2 | 3 | @safe @nogc pure nothrow: 4 | 5 | import test.testUtil : Test; 6 | import util.col.array : arraysEqual; 7 | import util.col.sortUtil : sortInPlace; 8 | import util.comparison : compareUint; 9 | 10 | void testSortUtil(ref Test test) { 11 | scope uint[3] xs = [3, 1, 2]; 12 | sortInPlace!(uint, compareUint)(xs); 13 | assert(arraysEqual!uint(xs, [1, 2, 3])); 14 | } 15 | -------------------------------------------------------------------------------- /test/end-to-end/compile-errors/expected-type-param.crow.out: -------------------------------------------------------------------------------- 1 | exit code: 1 2 | stderr: 3 | test/end-to-end/compile-errors/expected-type-param.crow 3:21-3:29 Expected type 'string'. 4 | Actual: 'nat64'. 5 | test/end-to-end/compile-errors/expected-type-param.crow 6:11-6:12 The literal doesn't match the expected type at this location. 6 | Expected type 't'. 7 | Uncaught exception: Reached compile error 8 | at foo 9 | at main 10 | -------------------------------------------------------------------------------- /include/crow/io/posix-util.crow: -------------------------------------------------------------------------------- 1 | no-std 2 | import 3 | system/errno: errno 4 | ../c-types: err-t 5 | ../exception: error 6 | ../misc: new, void 7 | ../number: == 8 | ../string: interpolate, show 9 | 10 | # Fail if `errno != 0`. 11 | check-errno void() summon, unsafe, (libc, native) extern 12 | errno check-posix-error 13 | 14 | # Fail if `e != 0`. 15 | check-posix-error void(e err-t) 16 | assert e == 0 : "posix error {e}" error 17 | -------------------------------------------------------------------------------- /test/end-to-end/compile-errors/builtin-does-not-exist.crow.out: -------------------------------------------------------------------------------- 1 | exit code: 0 2 | stderr: 3 | test/end-to-end/compile-errors/builtin-does-not-exist.crow 4:1-4:2 Crow does not implement a builtin type named 'x'. 4 | test/end-to-end/compile-errors/builtin-does-not-exist.crow 6:1-6:2 Crow does not implement a builtin spec named 'x'. 5 | test/end-to-end/compile-errors/builtin-does-not-exist.crow 9:1-9:3 Crow does not implement a builtin function named '=='. 6 | -------------------------------------------------------------------------------- /test/end-to-end/runnable/gc.crow.out: -------------------------------------------------------------------------------- 1 | stats: {"gc-count":0,"cur-word":131160,"words-used":131160,"words-free":130984} 2 | a: a=1, b=2, c=3 3 | stats (after print): {"gc-count":0,"cur-word":131928,"words-used":131928,"words-free":130216} 4 | -- after gc -- 5 | stats: {"gc-count":1,"cur-word":131147,"words-used":131150,"words-free":130994} 6 | a: a=1, b=2, c=3 7 | stats (after print): {"gc-count":1,"cur-word":131921,"words-used":131921,"words-free":130223} 8 | -------------------------------------------------------------------------------- /include/crow/symbol.crow: -------------------------------------------------------------------------------- 1 | no-std 2 | import 3 | ./col/array: array 4 | ./hash: hasher 5 | ./misc: void 6 | ./string: hash-mix, join, string 7 | export 8 | ./private/symbol-low-level: ==, <=>, symbol, to 9 | 10 | +show string(a symbol) 11 | a to 12 | 13 | +hash-mix void(hasher hasher, a symbol) 14 | hasher hash-mix a.to::string 15 | 16 | +to symbol(a symbol) bare 17 | a 18 | 19 | +interpolate symbol(...parts string[]) 20 | "" join parts to 21 | -------------------------------------------------------------------------------- /include/crow/fun-util.crow: -------------------------------------------------------------------------------- 1 | no-std 2 | 3 | # Calls the function and returns its return value. 4 | +subscript[r, p] r(a r function(x p), params p) builtin, bare 5 | 6 | +subscript[r, p] r(a r data(x p), params p) builtin 7 | 8 | # Calls the function and returns its return value. 9 | +subscript[r, p] r(a r shared(x p), params p) builtin 10 | 11 | # Calls the function and returns its return value. 12 | +subscript[r, p] r(a r mut(x p), params p) builtin 13 | -------------------------------------------------------------------------------- /test/unit/templates.crow: -------------------------------------------------------------------------------- 1 | dummy-templates nat() 2 | 0 3 | 4 | test 5 | f = 1::nat getter 6 | f[] is 1 7 | -getter[k] k data()(k k) k data 8 | () => k 9 | 10 | # Infer type arguments from explicit type of lambda 11 | test 12 | a = () sum-by (x nat) => x 13 | b = ("foo", "bar") sum-by (s symbol) => s.to::string.size 14 | a is 0 15 | b is 6 16 | -sum-by[t] nat(a t[], f nat mut(x t)) 17 | res mut nat = 0 18 | for x : a 19 | res +:= f[x] 20 | res 21 | -------------------------------------------------------------------------------- /editor/vscode/.vscode/launch.json: -------------------------------------------------------------------------------- 1 | // A launch configuration that compiles the extension and then opens it inside a new window 2 | { 3 | "version": "0.2.0", 4 | "configurations": [ 5 | { 6 | "type": "extensionHost", 7 | "request": "launch", 8 | "name": "Launch Client", 9 | "runtimeExecutable": "${execPath}", 10 | "args": ["--extensionDevelopmentPath=${workspaceRoot}"], 11 | "outFiles": ["${workspaceRoot}/*.js"], 12 | }, 13 | ] 14 | } 15 | -------------------------------------------------------------------------------- /test/end-to-end/compile-errors/auto-fun-errors.crow: -------------------------------------------------------------------------------- 1 | import 2 | crow/col/queue: queue 3 | 4 | main void() 5 | () 6 | 7 | r record 8 | 9 | to json(a r) bare 10 | 11 | blah json(a r) 12 | 13 | == bool(a r, b nat) 14 | 15 | to json(a r, b r) 16 | 17 | == bool(a ex, b ex) 18 | ex extern 19 | 20 | == bool(a en, b en) 21 | en enum(x) 22 | 23 | == comparison(a r, b r) 24 | <=> bool(a r, b r) 25 | to bool(a r) 26 | 27 | == bool(a nat queue, b nat queue) 28 | -------------------------------------------------------------------------------- /test/end-to-end/compile-errors/call-should-use-syntax.crow: -------------------------------------------------------------------------------- 1 | main void() 2 | xs string mut[] = "hello", "world" 3 | _ nat? = xs for-break x => break 0 4 | _ = ("a",)::string? force 5 | _ string[] = xs for-loop x => x reverse 6 | _ string[] = new 7 | _ string[] = "hello" new 8 | _ string[] = "hello" new "world" 9 | _ = xs.is-empty not 10 | xs set-subscript 0, "goodbye" 11 | _ = xs subscript 0 12 | _ void future = parallel with-block () => () 13 | () 14 | -------------------------------------------------------------------------------- /src/test/testMemory.d: -------------------------------------------------------------------------------- 1 | module test.testMemory; 2 | 3 | @safe @nogc pure nothrow: 4 | 5 | import test.testUtil : Test; 6 | import util.memory : memmove; 7 | 8 | @trusted void testMemory(ref Test) { 9 | ubyte[8] xs = [0, 1, 2, 3, 4, 5, 6, 7]; 10 | memmove(xs.ptr + 1, xs.ptr + 3, 5); 11 | assert(xs == [0, 3, 4, 5, 6, 7, 6, 7]); 12 | 13 | xs = [0, 1, 2, 3, 4, 5, 6, 7]; 14 | memmove(xs.ptr + 3, xs.ptr + 1, 3); 15 | assert(xs == [0, 1, 2, 1, 2, 3, 6, 7]); 16 | } 17 | -------------------------------------------------------------------------------- /test/end-to-end/compile-errors/name-not-found.crow.out: -------------------------------------------------------------------------------- 1 | exit code: 0 2 | stderr: 3 | test/end-to-end/compile-errors/name-not-found.crow 5:7-5:8 There is no type in scope named 't'. 4 | test/end-to-end/compile-errors/name-not-found.crow 6:13-6:14 There is no type in scope named 'x'. 5 | test/end-to-end/compile-errors/name-not-found.crow 11:5-11:6 There is no type in scope named 't'. 6 | test/end-to-end/compile-errors/name-not-found.crow 11:9-11:10 There is no spec in scope named 's'. 7 | -------------------------------------------------------------------------------- /test/unit/log.crow: -------------------------------------------------------------------------------- 1 | dummy-log nat() 2 | 0 3 | 4 | test native extern 5 | logs logged mut[] = () 6 | with : (shared log => logs ~= log) temp-log-handler 7 | info log "test" 8 | # Also works in fibers derived from this one 9 | fut void future = with : parallel 10 | warn log "test2" 11 | fut await 12 | error log "test3" 13 | logs.to::logged[] is ((info, "test"), (warn, "test2"), (error, "test3")) 14 | 15 | == bool(a logged, b logged) 16 | to json(a logged) 17 | -------------------------------------------------------------------------------- /test/end-to-end/compile-errors/extern-warnings.crow.out: -------------------------------------------------------------------------------- 1 | exit code: 0 2 | stderr: 3 | test/end-to-end/compile-errors/extern-warnings.crow 4:1-4:2 'bare' is redundant given 'extern'. 4 | test/end-to-end/compile-errors/extern-warnings.crow 6:1-6:2 'unsafe' is redundant given 'extern'. 5 | test/end-to-end/compile-errors/extern-warnings.crow 8:1-8:2 'summon' is redundant given 'extern'. 6 | test/end-to-end/compile-errors/extern-warnings.crow 10:1-10:2 A function is already 'pure' by default. 7 | -------------------------------------------------------------------------------- /test/end-to-end/compile-errors/modifier-conflict.crow.out: -------------------------------------------------------------------------------- 1 | exit code: 0 2 | stderr: 3 | test/end-to-end/compile-errors/modifier-conflict.crow 4:17-4:20 'mut' conflicts with 'data'. 4 | test/end-to-end/compile-errors/modifier-conflict.crow 6:16-6:22 'shared' conflicts with 'mut'. 5 | test/end-to-end/compile-errors/modifier-conflict.crow 8:26-8:32 'shared' conflicts with 'force-shared'. 6 | test/end-to-end/compile-errors/modifier-conflict.crow 10:21-10:27 'by-val' conflicts with 'by-ref'. 7 | -------------------------------------------------------------------------------- /test/unit/library/col/all.crow: -------------------------------------------------------------------------------- 1 | import 2 | ./frozen-map-tests: dummy-frozen-map-tests 3 | ./index-set-tests: dummy-index-set-tests 4 | ./array-tests: dummy-array-tests 5 | ./map-tests: dummy-map-tests 6 | ./mut-array-tests: dummy-mut-array-tests 7 | ./set-tests: dummy-set-tests 8 | 9 | dummy-col-tests nat() 10 | _ = dummy-array-tests 11 | _ = dummy-frozen-map-tests 12 | _ = dummy-index-set-tests 13 | _ = dummy-map-tests 14 | _ = dummy-mut-array-tests 15 | _ = dummy-set-tests 16 | -------------------------------------------------------------------------------- /demo/perf.crow: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env crow 2 | import 3 | crow/io/print 4 | crow/perf 5 | 6 | main void() summon, native extern 7 | xs nat[], perf perf-result = with : ("is-prime",) measure-performance 8 | with out : build 9 | for x : 2::nat .. 10000 10 | with : "is-prime" perf-measure 11 | if x is-prime 12 | out ~= x 13 | out print (" " join for x : xs; "{x}") 14 | out print "{perf}" 15 | () 16 | 17 | is-prime bool(a nat) 18 | 2::nat .. a !exists x => a is-multiple-of x 19 | -------------------------------------------------------------------------------- /test/end-to-end/parse-errors/enum-missing-name-value.crow.out: -------------------------------------------------------------------------------- 1 | exit code: 1 2 | stderr: 3 | test/end-to-end/parse-errors/enum-missing-name-value.crow 2:5-2:6 Expected a name (non-operator). 4 | test/end-to-end/parse-errors/enum-missing-name-value.crow 3:8-3:8 Expected an integer. 5 | test/end-to-end/parse-errors/enum-missing-name-value.crow 4:5-4:6 Expected a name (non-operator). 6 | test/end-to-end/parse-errors/enum-missing-name-value.crow 4:6-4:6 Expected an integer. 7 | Stopping due to compile errors. 8 | -------------------------------------------------------------------------------- /test/end-to-end/runnable/caught-exception-outside-of-task.crow: -------------------------------------------------------------------------------- 1 | import 2 | crow/private/thread-utils: create-one-thread, join-one-thread 3 | system/stdio: puts 4 | 5 | main void() summon, unsafe, (libc, native) extern 6 | thread = null create-one-thread &thread-fun 7 | thread join-one-thread 8 | info log "did join" 9 | 10 | -thread-fun any-mut-pointer(a any-mut-pointer) bare, summon, unsafe, libc extern 11 | _ = "will assert" puts 12 | assert 1::nat64 + 1 == 3 13 | _ = "did assert" puts 14 | a 15 | -------------------------------------------------------------------------------- /demo/open-gl/vertex.vert.essl: -------------------------------------------------------------------------------- 1 | #version 300 es 2 | 3 | uniform mat3 rotation; 4 | 5 | layout(location = 0) in vec3 vertPos; 6 | layout(location = 1) in vec3 vertNormal; 7 | layout(location = 2) in vec3 vertColor; 8 | layout(location = 3) in vec2 vertTextCoord; 9 | smooth out vec3 normal; 10 | smooth out vec3 color; 11 | smooth out vec2 texCoord; 12 | 13 | void main() { 14 | gl_Position = vec4(rotation * vertPos, 1.0); 15 | normal = rotation * vertNormal; 16 | color = vertColor; 17 | texCoord = vertTextCoord; 18 | } 19 | -------------------------------------------------------------------------------- /test/unit/library/col/mut-array-tests.crow: -------------------------------------------------------------------------------- 1 | dummy-mut-array-tests nat() 2 | 0 3 | 4 | test 5 | a nat8 mut[] = 1, 2, 3, 4, 5 6 | a pop-n-from-start 2 is (1, 2) 7 | a.to::nat8[] is (3, 4, 5) 8 | a pop-n 2 9 | a.to::nat8[] is (3,) 10 | a prepend= 2 11 | a.to::nat8[] is (2, 3) 12 | a insert-at 1, 5 13 | a.to::nat8[] is (2, 5, 3) 14 | a remove-at 1 is 5 15 | a.to::nat8[] is (2, 3) 16 | 17 | test 18 | a nat8 mut[] = 1, 2 19 | b nat8 mut[] = 3, 20 | a swap b 21 | a.to::nat8[] is (3,) 22 | b.to::nat8[] is (1, 2) 23 | -------------------------------------------------------------------------------- /include/crow/bool.crow: -------------------------------------------------------------------------------- 1 | no-std 2 | import 3 | ./compare: comparison 4 | ./private/number-low-level: ==, <=>, nat64, new 5 | export 6 | ./private/bool-low-level: &&, ||, bool, false, not, true 7 | 8 | # Same as `false`. 9 | +new bool() bare 10 | false 11 | 12 | # Boolean equality. 13 | +== bool(a bool, b bool) bare 14 | a.to == b.to 15 | 16 | # Compares `false` less than `true`. 17 | +<=> comparison(a bool, b bool) bare 18 | a.to <=> b.to 19 | 20 | # `0` for `false`, `1` for `true`. 21 | +to nat64(a bool) bare 22 | a ? 1 23 | -------------------------------------------------------------------------------- /include/system/string.crow: -------------------------------------------------------------------------------- 1 | no-std 2 | import 3 | crow/c-types: c-int, size_t 4 | crow/private/bootstrap: char8, nat8, const-pointer, mut-pointer 5 | 6 | +memcpy nat8 mut*(dest nat8 mut*, src nat8*, size size_t) libc extern, pure 7 | 8 | +memmove nat8 mut*(dest nat8 mut*, src nat8*, size size_t) libc extern, pure 9 | 10 | +memset nat8 mut*(begin nat8 mut*, value c-int, size size_t) libc extern, pure 11 | 12 | +memcmp c-int(s1 nat8*, s2 nat8*, n size_t) libc extern, pure 13 | 14 | +strlen size_t(a char8 mut*) libc extern, pure 15 | -------------------------------------------------------------------------------- /include/system/sys/types.crow: -------------------------------------------------------------------------------- 1 | no-std 2 | import 3 | crow/c-types: long-long, u-int, u-long, u-long-long 4 | crow/private/bootstrap: int32, nat32 5 | 6 | +blkcnt_t alias 7 | u-long 8 | +blksize_t alias 9 | u-long 10 | +dev_t alias 11 | u-long-long 12 | +gid_t alias 13 | u-long 14 | +ino_t alias 15 | u-long 16 | +mode_t alias 17 | u-int 18 | +nlink_t alias 19 | u-int 20 | +off_t alias 21 | long-long 22 | +pid_t alias 23 | int32 24 | +socklen_t alias 25 | nat32 26 | +time_t alias 27 | u-long 28 | +uid_t alias 29 | u-long 30 | -------------------------------------------------------------------------------- /src/frontend/lang.d: -------------------------------------------------------------------------------- 1 | module frontend.lang; 2 | 3 | @safe @nogc pure nothrow: 4 | 5 | import util.symbol : Symbol, symbol; 6 | 7 | Symbol crowConfigBaseName() => symbol!"crow-config.json"; 8 | 9 | immutable struct JitOptions { 10 | OptimizationLevel optimization; 11 | } 12 | 13 | enum CVersion { c99, c11 } 14 | 15 | immutable struct CCompileOptions { 16 | OptimizationLevel optimizationLevel; 17 | CVersion cVersion; 18 | } 19 | 20 | enum OptimizationLevel { 21 | none, 22 | o2, 23 | } 24 | 25 | size_t maxSpecDepth() => 8; 26 | -------------------------------------------------------------------------------- /src/util/col/set.d: -------------------------------------------------------------------------------- 1 | module util.col.set; 2 | 3 | @safe @nogc pure nothrow: 4 | 5 | import util.col.mutSet : MutSet; 6 | 7 | immutable struct Set(T) { 8 | @safe @nogc pure nothrow: 9 | 10 | private MutSet!(T) inner; 11 | 12 | bool opBinaryRight(string op)(in T x) scope if (op == "in") => 13 | x in inner; 14 | 15 | int opApply(in int delegate(ref immutable T) @safe @nogc pure nothrow cb) scope => 16 | inner.opApply(cb); 17 | } 18 | 19 | @trusted Set!T moveToSet(T)(ref MutSet!T a) => 20 | Set!T(cast(immutable) a.move()); 21 | -------------------------------------------------------------------------------- /test/end-to-end/compile-errors/option-call-errors.crow.out: -------------------------------------------------------------------------------- 1 | exit code: 1 2 | stderr: 3 | test/end-to-end/compile-errors/option-call-errors.crow 4:14-4:17 Expected type 'int64?'. 4 | Actual: 'int64'. 5 | test/end-to-end/compile-errors/option-call-errors.crow 5:13-5:25 Expected type 'nat64'. 6 | Actual: 'nat64?'. 7 | test/end-to-end/compile-errors/option-call-errors.crow 6:9-6:12 Expected one of these types: 8 | 'int64?' 9 | 'float32?' 10 | 'float64?' 11 | Actual: 'int64'. 12 | Uncaught exception: Reached compile error 13 | at main 14 | -------------------------------------------------------------------------------- /test/end-to-end/compile-errors/type-annotation-unnecessary.crow.out: -------------------------------------------------------------------------------- 1 | exit code: 0 2 | stdout: 3 | info: 0 4 | stderr: 5 | test/end-to-end/compile-errors/type-annotation-unnecessary.crow 2:14-2:19 Type annotation is unnecessary; type 'nat64' was already inferred. 6 | test/end-to-end/compile-errors/type-annotation-unnecessary.crow 3:20-3:28 Type annotation is unnecessary; type 'string' was already inferred. 7 | test/end-to-end/compile-errors/type-annotation-unnecessary.crow 3:29-3:35 Type annotation is unnecessary; type 'void' was already inferred. 8 | -------------------------------------------------------------------------------- /test/end-to-end/compile-errors/extern-type-errors.crow.out: -------------------------------------------------------------------------------- 1 | exit code: 0 2 | stderr: 3 | test/end-to-end/compile-errors/extern-type-errors.crow 7:5-7:8 Type 'r' has purity 'data', but member of type 'a' has purity 'mut'. 4 | test/end-to-end/compile-errors/extern-type-errors.crow 9:3-9:4 An extern type can't have type parameters. 5 | test/end-to-end/compile-errors/extern-type-errors.crow 11:10-11:20 A value of type 'nat32' must be from 0 to 4294967295. 6 | test/end-to-end/compile-errors/extern-type-errors.crow 11:22-11:23 Alignment must be 1, 2, 4, or 8. 7 | -------------------------------------------------------------------------------- /test/end-to-end/compile-errors/alias-not-allowed.crow.out: -------------------------------------------------------------------------------- 1 | exit code: 1 2 | stderr: 3 | test/end-to-end/compile-errors/alias-not-allowed.crow 2:13-2:14 The literal doesn't match the expected type at this location. 4 | Expected type '<>'. 5 | test/end-to-end/compile-errors/alias-not-allowed.crow 5:5-5:8 An alias is not allowed to reference another alias in the same module. 6 | test/end-to-end/compile-errors/alias-not-allowed.crow 8:5-8:8 An alias is not allowed to reference another alias in the same module. 7 | Uncaught exception: Reached compile error 8 | at main 9 | -------------------------------------------------------------------------------- /include/crow/std.crow: -------------------------------------------------------------------------------- 1 | no-std 2 | export 3 | ./bits 4 | ./bool 5 | ./col/array 6 | ./col/collection 7 | ./col/map 8 | ./col/mut-array 9 | ./col/mut-map 10 | ./col/mut-set 11 | ./col/set 12 | ./col/shared-array 13 | ./col/shared-map 14 | ./col/sort 15 | ./col/util 16 | ./compare 17 | ./enum-util 18 | ./exception 19 | ./flags-util 20 | ./fun-util 21 | ./hash 22 | ./json 23 | ./log 24 | ./misc 25 | ./number 26 | ./option 27 | ./parallel 28 | ./pointer 29 | ./range 30 | ./result 31 | ./string 32 | ./symbol 33 | ./test-util 34 | ./tuple 35 | -------------------------------------------------------------------------------- /demo/libraries/SDL2/SDL.crow: -------------------------------------------------------------------------------- 1 | # SDL.h 2 | 3 | import 4 | crow/c-types: c-int 5 | 6 | +SDL_Init c-int(init-flags SDL_Init_flags) SDL2 extern 7 | 8 | +SDL_Init_flags flags extern, nat32 storage 9 | SDL_INIT_TIMER = 0x00000001 10 | SDL_INIT_AUDIO = 0x00000010 11 | SDL_INIT_VIDEO = 0x00000020 12 | SDL_INIT_CDROM = 0x00000100 13 | SDL_INIT_JOYSTICK = 0x00000200 14 | SDL_INIT_NOPARACHUTE = 0x00100000 15 | SDL_INIT_EVENTTHREAD = 0x01000000 16 | SDL_INIT_EVERYTHING = 0x0000FFFF 17 | 18 | +SDL_Quit void() SDL2 extern 19 | 20 | +SDL_GetError c-string() SDL2 extern 21 | -------------------------------------------------------------------------------- /include/crow/tuple.crow: -------------------------------------------------------------------------------- 1 | no-std 2 | import 3 | ./bool: bool 4 | ./compare: compare, comparison, equal 5 | export 6 | ./private/bootstrap: a, b, c, d, e, f, g, h, i, new, tuple2, tuple3, tuple4, tuple5, tuple6 7 | 8 | +==[t0, t1] bool(a (t0, t1), b (t0, t1)) bare, t0 equal, t1 equal 9 | +<=>[t0, t1] comparison(a (t0, t1), b (t0, t1)) bare, t0 compare, t1 compare 10 | 11 | +==[t0, t1, t2] bool(a (t0, t1, t2), b (t0, t1, t2)) bare, t0 equal, t1 equal, t2 equal 12 | +<=>[t0, t1, t2] comparison(a (t0, t1, t2), b (t0, t1, t2)) bare, t0 compare, t1 compare, t2 compare 13 | -------------------------------------------------------------------------------- /include/crow/col/private/build.crow: -------------------------------------------------------------------------------- 1 | no-std 2 | import 3 | ../../misc: void 4 | ../../number: nat64 5 | 6 | +builder[col, builder] spec 7 | build col(options build-options, f void mut(out builder)) 8 | +build[col, elem, builder] spec (col, builder) builder 9 | ~= void(a builder, value elem) 10 | +build-options record 11 | size-hint nat64 12 | +build build-options() 13 | 0, 14 | +build build-options(size-hint nat64) 15 | size-hint, 16 | +with-block[col, builder] col( 17 | a build-options, 18 | f void mut(out builder), 19 | ) (col, builder) builder 20 | a build f 21 | -------------------------------------------------------------------------------- /test/end-to-end/parse-errors/need-block-context.crow.out: -------------------------------------------------------------------------------- 1 | exit code: 1 2 | stderr: 3 | test/end-to-end/parse-errors/need-block-context.crow 2:8-2:10 'if' expression must appear in a context where it can be followed by an indented block. 4 | test/end-to-end/parse-errors/need-block-context.crow 6:11-6:16 'match' expression must appear in a context where it can be followed by an indented block. 5 | test/end-to-end/parse-errors/need-block-context.crow 11:11-11:16 Lambda expression must appear in a context where it can be followed by an indented block. 6 | Stopping due to compile errors. 7 | -------------------------------------------------------------------------------- /test/end-to-end/compile-errors/fun-closure-errors.crow: -------------------------------------------------------------------------------- 1 | main void() summon 2 | fut void future = (), 3 | 4 | x mut nat = 0 5 | _ nat data() = () => 6 | _ = fut 7 | 1 8 | _ nat shared() = () => x 9 | 10 | y nat mut[] = 0, 11 | _ nat mut[] data() = () => y 12 | _ nat mut[] shared() = () => y 13 | 14 | _ void data() = () => sum 15 | _ void data() = () => 16 | f void mut() = () => sum 17 | f[] 18 | _ void data() = () => 19 | uses-spec 20 | () 21 | 22 | uses-spec void() sum 23 | () 24 | 25 | sum spec 26 | sum void() 27 | 28 | sum void() summon 29 | () 30 | -------------------------------------------------------------------------------- /test/end-to-end/compile-errors/spec-multiple-impls.crow.out: -------------------------------------------------------------------------------- 1 | exit code: 1 2 | stderr: 3 | test/end-to-end/compile-errors/spec-multiple-impls.crow 9:31-9:45 There are functions named 'to-json-string', but they do not match the expected return type and actual argument types. 4 | Expected return type 'void'. 5 | Actual argument types: (Other arguments not checked; gave up early.) 6 | Candidates (with 1 arguments): 7 | 'to-json-string[t] string(a t)' (from test/end-to-end/compile-errors/spec-multiple-impls.crow line 5) 8 | Uncaught exception: Reached compile error 9 | at main 10 | -------------------------------------------------------------------------------- /demo/parallel.crow: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env crow 2 | import 3 | crow/io/print: out, print 4 | crow/private/thread-utils: count-processors 5 | crow/version: is-interpreted 6 | 7 | main nat(_ string[]) summon 8 | if trusted is-interpreted 9 | warn log "Try with '--aot'" 10 | if trusted extern native 11 | out print "running with {trusted count-processors} processors" 12 | primes nat[] = (1_000_000::nat .. 1_010_000) chunked-parallel 100 filter x => x is-prime 13 | out print "primes: {primes.to::json}" 14 | () 15 | 16 | is-prime bool(a nat) 17 | 2::nat .. a !exists x => a is-multiple-of x 18 | -------------------------------------------------------------------------------- /test/end-to-end/compile-errors/extern-unnecessary-library-name.crow.out: -------------------------------------------------------------------------------- 1 | exit code: 0 2 | stderr: 3 | test/end-to-end/compile-errors/extern-unnecessary-library-name.crow 4:9-4:20 'extern' does not take a type argument in this context. 4 | test/end-to-end/compile-errors/extern-unnecessary-library-name.crow 5:10-5:21 'extern' does not take a type argument in this context. 5 | test/end-to-end/compile-errors/extern-unnecessary-library-name.crow 6:1-6:23 A union can't be 'extern'. 6 | test/end-to-end/compile-errors/extern-unnecessary-library-name.crow 6:12-6:23 'extern' does not take a type argument in this context. 7 | -------------------------------------------------------------------------------- /test/end-to-end/compile-errors/lambda-errors.crow.out: -------------------------------------------------------------------------------- 1 | exit code: 1 2 | stderr: 3 | test/end-to-end/compile-errors/lambda-errors.crow 2:9-2:16 Lambda expression needs an expected type. 4 | test/end-to-end/compile-errors/lambda-errors.crow 3:11-3:27 The lambda doesn't match the expected type at this location. 5 | Expected type 'void mut(nat64)'. 6 | test/end-to-end/compile-errors/lambda-errors.crow 4:11-4:18 Multiple lambda types are possible: 7 | 'void mut(nat64)' 8 | 'void mut(string)' 9 | Consider explicitly typing the lambda's parameter. 10 | Uncaught exception: Reached compile error 11 | at main 12 | -------------------------------------------------------------------------------- /test/end-to-end/compile-errors/variant-multiple-members-with-name.crow.out: -------------------------------------------------------------------------------- 1 | exit code: 1 2 | stderr: 3 | test/end-to-end/compile-errors/variant-multiple-members-with-name.crow 2:11-2:12 Cannot choose an overload of 'x'. Multiple functions match: 4 | 'x v()' (from test/end-to-end/compile-errors/variant-multiple-members-with-name.crow line 11) 5 | 'x v()' (from test/end-to-end/compile-errors/variant-multiple-members-with-name.crow line 12) 6 | test/end-to-end/compile-errors/variant-multiple-members-with-name.crow 12:1-12:2 Type name 'x' is already used. 7 | Uncaught exception: Reached compile error 8 | at main 9 | -------------------------------------------------------------------------------- /test/end-to-end/compile-errors/modifier-duplicate-or-redundant.crow: -------------------------------------------------------------------------------- 1 | main void() 2 | () 3 | 4 | f void() bare, bare, libc extern, native extern 5 | 6 | nat64 builtin data 7 | 8 | e extern mut 9 | 10 | ee extern extern 11 | 12 | en enum(x) data 13 | 14 | f flags data 15 | 16 | r record data 17 | 18 | u union(x) data 19 | 20 | uv union(x) by-val 21 | 22 | dd extern data, data 23 | 24 | mm record mut, mut 25 | 26 | ss record shared, shared 27 | 28 | rr record by-ref, by-ref 29 | 30 | vv record by-val, by-val 31 | 32 | g global(nat) libc extern, native extern 33 | 34 | data spec builtin, builtin 35 | -------------------------------------------------------------------------------- /test/end-to-end/compile-errors/call-flags.crow: -------------------------------------------------------------------------------- 1 | main void() bare 2 | ()::string foo 3 | ()::(string array) foo 4 | ()::(string array array) foo 5 | 6 | ()::bool foo 7 | ()::(bool array) foo 8 | ()::(bool array array) foo 9 | 10 | ()::nat foo 11 | ()::(nat array) foo 12 | ()::(nat array array) foo 13 | 14 | _ nat array = 1, 15 | 16 | # testing indirect call flags 17 | foo[t] spec 18 | foo void(a t) 19 | 20 | foo[t] void(a t array) bare, t foo 21 | if false 22 | a[0] foo 23 | 24 | foo void(_ string) bare, unsafe 25 | () 26 | 27 | foo void(_ bool) 28 | () 29 | 30 | foo void(_ nat) bare, summon 31 | () 32 | -------------------------------------------------------------------------------- /test/end-to-end/compile-errors/destructure-errors.crow.out: -------------------------------------------------------------------------------- 1 | exit code: 1 2 | stderr: 3 | test/end-to-end/compile-errors/destructure-errors.crow 5:5-5:12 Expected type 'bool', but got 'nat64'. 4 | test/end-to-end/compile-errors/destructure-errors.crow 6:26-6:27 Expected type '(bool, symbol)'. 5 | Actual: '(nat64, string)'. 6 | test/end-to-end/compile-errors/destructure-errors.crow 8:5-8:15 Expected a tuple with 3 elements, but got '(nat64, string)'. 7 | test/end-to-end/compile-errors/destructure-errors.crow 9:5-9:11 Expected a tuple with 2 elements, but got 'nat64'. 8 | Uncaught exception: Reached compile error 9 | at main 10 | -------------------------------------------------------------------------------- /test/end-to-end/compile-errors/trusted-unnecessary.crow.out: -------------------------------------------------------------------------------- 1 | exit code: 0 2 | stderr: 3 | test/end-to-end/compile-errors/trusted-unnecessary.crow 5:5-5:12 'trusted' expression is redundant inside an 'unsafe' function. 4 | test/end-to-end/compile-errors/trusted-unnecessary.crow 8:13-8:20 'trusted' expression is redundant inside another 'trusted' expression. 5 | test/end-to-end/compile-errors/trusted-unnecessary.crow 12:13-12:20 There is no unsafe code in this expression; you could remove 'trusted'. 6 | test/end-to-end/compile-errors/trusted-unnecessary.crow 13:5-13:12 There is no unsafe code in this expression; you could remove 'trusted'. 7 | -------------------------------------------------------------------------------- /test/unit/library/bare-queue-tests.crow: -------------------------------------------------------------------------------- 1 | import 2 | ../../../include/crow/private/bare-queue 3 | 4 | dummy-bare-queue-tests nat() 5 | 0 6 | 7 | -queue record nominal 8 | -with-block void(_ queue, cb void mut(queue nat bare-queue mut*)) unsafe, native extern 9 | queue mut nat bare-queue = () 10 | a nat bare-queue mut* = &queue 11 | finally a destroy 12 | cb[a] 13 | 14 | test trusted, native extern 15 | with a : queue 16 | assert a.as-const is-empty 17 | for i : 0::nat64 .. 3 18 | a enqueue i 19 | forbid a.as-const is-empty 20 | for i : 0::nat64 .. 3 21 | a.dequeue is (i,) 22 | assert a.as-const is-empty 23 | -------------------------------------------------------------------------------- /editor/vscode/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "crow", 3 | "displayName": "Crow Programming Language", 4 | "description": "IDE support for Crow", 5 | "publisher": "crow", 6 | "version": "0.0.0", 7 | "engines": { 8 | "vscode": "^1.84.2" 9 | }, 10 | "activationEvents": [ 11 | "onLanguage:crow" 12 | ], 13 | "main": "./index.js", 14 | "contributes": { 15 | "languages": [ 16 | { 17 | "id": "crow", 18 | "extensions": [ 19 | ".crow" 20 | ] 21 | } 22 | ] 23 | }, 24 | "dependencies": { 25 | "vscode-languageclient": "^9.0.1" 26 | }, 27 | "devDependencies": { 28 | "@vscode/vsce": "^2.24.0" 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /test/end-to-end/compile-errors/extern-invalid-name.crow.out: -------------------------------------------------------------------------------- 1 | exit code: 1 2 | stderr: 3 | test/end-to-end/compile-errors/extern-invalid-name.crow 2:15-2:18 'bar' is not a builtin extern name and is not configured in 'crow-config.json' 4 | test/end-to-end/compile-errors/extern-invalid-name.crow 3:9-3:12 Function 'foo void()' (from test/end-to-end/compile-errors/extern-invalid-name.crow line 5) requires extern 'bogus', but that is not in scope. 5 | test/end-to-end/compile-errors/extern-invalid-name.crow 5:12-5:15 'bar' is not a builtin extern name and is not configured in 'crow-config.json' 6 | Uncaught exception: Reached compile error 7 | at main 8 | -------------------------------------------------------------------------------- /test/end-to-end/compile-errors/type-params-unsupported.crow.out: -------------------------------------------------------------------------------- 1 | exit code: 0 2 | stderr: 3 | test/end-to-end/compile-errors/type-params-unsupported.crow 4:3-4:4 An extern function can't have type parameters. 4 | test/end-to-end/compile-errors/type-params-unsupported.crow 5:4-5:5 An extern type can't have type parameters. 5 | test/end-to-end/compile-errors/type-params-unsupported.crow 6:5-6:6 A type alias can't have type parameters. 6 | test/end-to-end/compile-errors/type-params-unsupported.crow 8:3-8:4 An enum type can't have type parameters. 7 | test/end-to-end/compile-errors/type-params-unsupported.crow 9:3-9:4 A flags type can't have type parameters. 8 | -------------------------------------------------------------------------------- /include/system/errno.crow: -------------------------------------------------------------------------------- 1 | no-std 2 | import 3 | crow/c-types: err-t 4 | crow/pointer: *, mut-pointer 5 | ../crow/private/bootstrap: todo 6 | 7 | +errno err-t() bare, summon, unsafe, (libc, native) extern 8 | if extern ucrtbase 9 | *_errno 10 | elif extern posix 11 | *__errno_location 12 | else 13 | todo 14 | -_errno err-t mut*() ucrtbase extern 15 | -__errno_location err-t mut*() posix extern 16 | 17 | +ENOENT err-t() bare 18 | 2 19 | +ESRCH err-t() bare 20 | 3 21 | +EAGAIN err-t() bare 22 | 11 23 | +EWOULDBLOCK err-t() bare 24 | EAGAIN 25 | +EEXIST err-t() bare 26 | 17 27 | +EINVAL err-t() bare 28 | 22 29 | +ETIMEDOUT err-t() bare 30 | 110 31 | -------------------------------------------------------------------------------- /test/end-to-end/compile-errors/variant-member-multiple.crow.out: -------------------------------------------------------------------------------- 1 | exit code: 1 2 | stderr: 3 | test/end-to-end/compile-errors/variant-member-multiple.crow 3:18-3:19 There are functions named 'r', but they do not match the expected return type and actual argument types. 4 | Expected return type 'string v'. 5 | Actual argument types: 6 | Candidates (with 0 arguments): 7 | 'r nat64 v()' (from test/end-to-end/compile-errors/variant-member-multiple.crow line 7) 8 | test/end-to-end/compile-errors/variant-member-multiple.crow 7:32-7:55 Type 'r' can't declare itself a member of the same variant 'v' multiple times. 9 | Uncaught exception: Reached compile error 10 | at main 11 | -------------------------------------------------------------------------------- /demo/sound/play-file.crow: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env crow 2 | import 3 | crow/io/print: out, print 4 | crow/io/stdin: read-stdin 5 | audio/audio: format, play-loop, shut-down 6 | audio/sdl-audio: start-sdl-audio 7 | audio/read-sound-file: read-sound-file 8 | audio/sound: sample-rate, with-sample-rate 9 | 10 | main nat(args string[]) summon, (native, sndfile, SDL2) extern 11 | assert args.size == 1 : "Usage: crow play-file.crow toccata.ogg" error 12 | audio = start-sdl-audio 13 | sound = args[0].read-sound-file with-sample-rate audio.format.sample-rate 14 | _ = audio play-loop sound 15 | out print "Press enter to exit" 16 | _ = read-stdin 17 | audio shut-down 18 | 0 19 | -------------------------------------------------------------------------------- /test/unit/pointers.crow: -------------------------------------------------------------------------------- 1 | dummy-pointers nat() 2 | 0 3 | 4 | test trusted, native extern 5 | r mut r = 0, 6 | rp r mut* = &r 7 | x nat mut* = rp x 8 | *x := 3 9 | assert x == &rp->x 10 | 11 | rc r* = &r 12 | xc nat* = rc x 13 | assert xc == &rc->x 14 | assert *xc == r.x 15 | *xc is 3 16 | -r record by-val, mut 17 | x mut nat 18 | 19 | test trusted, native extern 20 | x mut nat = 0 21 | get-x nat mut() = () => 22 | x 23 | set-x void mut() = () => 24 | x := 1 25 | 26 | get-x[] is 0 27 | &x assert-value 0 28 | 29 | set-x[] 30 | get-x[] is 1 31 | &x assert-value 1 32 | -assert-value void(x nat*, value nat) unsafe, native extern 33 | *x is value 34 | -------------------------------------------------------------------------------- /test/end-to-end/compile-errors/duplicate-declaration.crow: -------------------------------------------------------------------------------- 1 | main void() 2 | () 3 | 4 | foo record 5 | a nat 6 | a nat 7 | 8 | foo union 9 | b 10 | b nat 11 | 12 | foo enum 13 | c 14 | c 15 | 16 | foo flags 17 | d 18 | d 19 | 20 | s spec 21 | s spec 22 | 23 | f nat(a nat, a nat) 24 | a 25 | 26 | f nat() 27 | a nat = 1 28 | a nat = 2 29 | a 30 | 31 | f nat(a nat) 32 | a nat = 1 33 | a 34 | 35 | f nat() 36 | 1 call a => 37 | a nat = 1 38 | a 39 | 40 | f nat() 41 | 1 call a => 42 | b nat = 1 43 | 1 call b => 44 | a nat = 2 45 | b 46 | 47 | f nat() 48 | 1 call a => 49 | 1 call a => 50 | a 51 | 52 | call nat(_ nat, f nat data(x nat)) 53 | f[0] 54 | -------------------------------------------------------------------------------- /include/crow/private/bool-low-level.crow: -------------------------------------------------------------------------------- 1 | no-std 2 | export 3 | ./bootstrap: bool 4 | 5 | ### 6 | False boolean value. 7 | This can also be written as `()`. 8 | ### 9 | +false bool() builtin, bare 10 | 11 | # True boolean value. 12 | +true bool() builtin, bare 13 | 14 | # Changes `true` to `false`, and `false` to `true`. 15 | +not bool(a bool) builtin, bare 16 | 17 | ### 18 | If `a` is `false`, returns `false` immediately and does not evaluate `b`. 19 | Else, returns `b`. 20 | ### 21 | +&& bool(a bool, b bool) builtin, bare 22 | 23 | ### 24 | If `a` is `true`, returns `true` immediately and does not evaluate `b`. 25 | Else, returns `b`. 26 | ### 27 | +|| bool(a bool, b bool) builtin, bare 28 | -------------------------------------------------------------------------------- /include/system/netinet/in.crow: -------------------------------------------------------------------------------- 1 | no-std 2 | import 3 | crow/number: nat16, nat32, nat64 4 | system/sys/socket: sa_family_t 5 | 6 | +in_addr_t alias 7 | nat32 8 | +in_addr record(s-addr in_addr_t) extern 9 | 10 | +in_port_t alias 11 | nat16 12 | 13 | # Same size as sockaddr 14 | +sockaddr_in record by-val 15 | # 2 bytes 16 | sin_family sa_family_t 17 | # 2 bytes 18 | sin_port in_port_t 19 | # 4 bytes 20 | sin_addr in_addr 21 | -padding nat64 22 | 23 | +new sockaddr_in(sin_family sa_family_t, sin_port in_port_t, sin_addr in_addr) bare 24 | sin_family, sin_port, sin_addr, 0 25 | 26 | +new sockaddr_in() bare 27 | 0, 0, (0,) 28 | 29 | +htons nat16(hostshort nat16) posix extern, pure 30 | -------------------------------------------------------------------------------- /test/end-to-end/compile-errors/shared-lambda-errors.crow.out: -------------------------------------------------------------------------------- 1 | exit code: 1 2 | stderr: 3 | test/end-to-end/compile-errors/shared-lambda-errors.crow 3:22-3:28 Argument to 'shared' must be a lambda expression. 4 | test/end-to-end/compile-errors/shared-lambda-errors.crow 4:28-4:34 Expected type is a lambda, but it is not 'shared'. 5 | Expected type 'nat64 mut()'. 6 | test/end-to-end/compile-errors/shared-lambda-errors.crow 5:42-5:48 'shared' lambda needs a 'shared' parameter type, but it is 'nat64 mut[]'. 7 | test/end-to-end/compile-errors/shared-lambda-errors.crow 6:37-6:43 'shared' lambda needs a 'shared' return type, but it is 'nat64 mut[]'. 8 | Uncaught exception: Reached compile error 9 | at main 10 | -------------------------------------------------------------------------------- /test/end-to-end/compile-errors/circular-import-a.crow.out: -------------------------------------------------------------------------------- 1 | exit code: 1 2 | stderr: 3 | test/end-to-end/compile-errors/circular-import-a.crow 2:5-2:24 This is part of a circular import: 4 | test/end-to-end/compile-errors/circular-import-a.crow imports 5 | test/end-to-end/compile-errors/circular-import-b.crow imports 6 | test/end-to-end/compile-errors/circular-import-a.crow 7 | test/end-to-end/compile-errors/circular-import-b.crow 2:5-2:24 This is part of a circular import: 8 | test/end-to-end/compile-errors/circular-import-b.crow imports 9 | test/end-to-end/compile-errors/circular-import-a.crow imports 10 | test/end-to-end/compile-errors/circular-import-b.crow 11 | Stopping due to compile errors. 12 | -------------------------------------------------------------------------------- /test/end-to-end/compile-errors/circular-import-b.crow.out: -------------------------------------------------------------------------------- 1 | exit code: 1 2 | stderr: 3 | test/end-to-end/compile-errors/circular-import-a.crow 2:5-2:24 This is part of a circular import: 4 | test/end-to-end/compile-errors/circular-import-a.crow imports 5 | test/end-to-end/compile-errors/circular-import-b.crow imports 6 | test/end-to-end/compile-errors/circular-import-a.crow 7 | test/end-to-end/compile-errors/circular-import-b.crow 2:5-2:24 This is part of a circular import: 8 | test/end-to-end/compile-errors/circular-import-b.crow imports 9 | test/end-to-end/compile-errors/circular-import-a.crow imports 10 | test/end-to-end/compile-errors/circular-import-b.crow 11 | Stopping due to compile errors. 12 | -------------------------------------------------------------------------------- /test/unit/crow-parser/all.crow: -------------------------------------------------------------------------------- 1 | ### 2 | Tests of successful edge cases in the crow parser. 3 | Error tests go in test/end-to-end/parse-errors . 4 | ### 5 | import 6 | ./comments: dummy-comments 7 | ./line-continuation: dummy-line-continuation 8 | ./no-trailing-comma: dummy-no-trailing-comma 9 | ./operator-precedence: dummy-operator-precedence 10 | ./pointers: dummy-pointers 11 | ./strings: dummy-strings 12 | ./trailing-indent: dummy-trailing-indent 13 | 14 | dummy-crow-parser nat() 15 | _ = dummy-comments 16 | _ = dummy-line-continuation 17 | _ = dummy-no-trailing-comma 18 | _ = dummy-operator-precedence 19 | _ = dummy-pointers 20 | _ = dummy-strings 21 | _ = dummy-trailing-indent 22 | 0 23 | -------------------------------------------------------------------------------- /demo/open-gl/load-bmp.crow: -------------------------------------------------------------------------------- 1 | import 2 | SDL2/SDL_pixels: SDL_PIXELFORMAT_RGBA32 3 | SDL2/SDL_rwops: SDL_RWFromConstMem 4 | SDL2/SDL_surface: h, pixels, SDL_ConvertSurfaceFormat, SDL_LoadBMP_RW, SDL_FreeSurface, w 5 | 6 | rgba-image record(image-data nat8 mut*, width nat64, height nat64) mut 7 | 8 | with-bmp[t] t(src nat8[], cb t mut(image rgba-image)) summon, unsafe, (native, SDL2) extern 9 | surface = src.begin-pointer SDL_RWFromConstMem src.size.to SDL_LoadBMP_RW 0 10 | converted = surface SDL_ConvertSurfaceFormat SDL_PIXELFORMAT_RGBA32, 0 11 | surface SDL_FreeSurface 12 | image rgba-image = converted->pixels, converted->w.to, converted->h.to 13 | res = cb[image] 14 | converted SDL_FreeSurface 15 | res 16 | -------------------------------------------------------------------------------- /test/unit/function-pointers.crow: -------------------------------------------------------------------------------- 1 | dummy-function-pointers nat() 2 | 0 3 | 4 | test 5 | xs string mut[] = () 6 | res = xs.get-fun-void[xs ~= "arg"] 7 | xs.move-to::string[] is ("get-fun", "arg") 8 | res is 3 9 | 10 | -get-fun-void nat function()(xs string mut[]) 11 | xs ~= "get-fun" 12 | &foo 13 | -foo nat() bare 14 | 3 15 | 16 | test 17 | xs string mut[] = () 18 | res = xs.get-fun-tuple[xs get-pair] 19 | xs.move-to::string[] is ("get-fun", "get-pair") 20 | res is 3 21 | 22 | -get-fun-tuple nat function(x bool, y char8)(xs string mut[]) 23 | xs ~= "get-fun" 24 | &foo 25 | -foo nat(_ bool, _ char8) bare 26 | 3 27 | 28 | -get-pair (bool, char8)(xs string mut[]) 29 | xs ~= "get-pair" 30 | true, "a" 31 | -------------------------------------------------------------------------------- /test/end-to-end/compile-errors/record-field-visibility-warnings.crow.out: -------------------------------------------------------------------------------- 1 | exit code: 0 2 | stderr: 3 | test/end-to-end/compile-errors/record-field-visibility-warnings.crow 5:5-5:6 Field 'x' should not be more visible than record 'r' which is only internal. 4 | test/end-to-end/compile-errors/record-field-visibility-warnings.crow 7:2-7:3 's' is unused. 5 | test/end-to-end/compile-errors/record-field-visibility-warnings.crow 8:5-8:6 Field 'x' should not be more visible than record 's' which is only private. 6 | test/end-to-end/compile-errors/record-field-visibility-warnings.crow 10:2-10:3 't' is unused. 7 | test/end-to-end/compile-errors/record-field-visibility-warnings.crow 11:5-11:6 Fields of record 't' are already private by default. 8 | -------------------------------------------------------------------------------- /include/system/fcntl.crow: -------------------------------------------------------------------------------- 1 | no-std 2 | import 3 | crow/c-types: c-int, fd-t 4 | crow/number: nat32 5 | crow/string: c-string 6 | 7 | +fcntl c-int(fd fd-t, cmd c-int, oflags oflag-t) posix extern 8 | 9 | +F_DUPFD c-int() bare 10 | 0 11 | +F_GETFD c-int() bare 12 | 1 13 | +F_SETFD c-int() bare 14 | 2 15 | +F_GETFL c-int() bare 16 | 3 17 | +F_SETFL c-int() bare 18 | 4 19 | 20 | +open fd-t(path c-string, oflag oflag-t, permission nat32) posix extern 21 | 22 | +oflag-t alias 23 | c-int 24 | 25 | +O_RDONLY oflag-t() bare 26 | 0 27 | +O_WRONLY oflag-t() bare 28 | 1 29 | +O_RDWR oflag-t() bare 30 | 2 31 | +O_CREAT oflag-t() bare 32 | 0x40 33 | +O_TRUNC oflag-t() bare 34 | 0x200 35 | +O_NONBLOCK oflag-t() bare 36 | 0x800 37 | -------------------------------------------------------------------------------- /src/concretize/constantsOrExprs.d: -------------------------------------------------------------------------------- 1 | module concretize.constantsOrExprs; 2 | 3 | @safe @nogc pure nothrow: 4 | 5 | import model.concreteModel : ConcreteExpr; 6 | import model.constant : Constant; 7 | import util.alloc.alloc : Alloc; 8 | import util.col.array : every, map, SmallArray; 9 | import util.union_ : TaggedUnion; 10 | 11 | immutable struct ConstantsOrExprs { 12 | mixin TaggedUnion!(SmallArray!Constant, SmallArray!ConcreteExpr); 13 | } 14 | 15 | ConstantsOrExprs asConstantsOrExprs(ref Alloc alloc, ConcreteExpr[] exprs) => 16 | every!ConcreteExpr(exprs, (in ConcreteExpr arg) => arg.kind.isA!Constant) 17 | ? ConstantsOrExprs(map(alloc, exprs, (ref ConcreteExpr arg) => arg.kind.as!Constant)) 18 | : ConstantsOrExprs(exprs); 19 | -------------------------------------------------------------------------------- /test/unit/library/bits-tests.crow: -------------------------------------------------------------------------------- 1 | dummy-bits-tests nat64() 2 | 0 3 | 4 | test 5 | 0.high-n-bits is 0 6 | 1.high-n-bits is 0b1000000000000000000000000000000000000000000000000000000000000000 7 | 13.high-n-bits is 0b1111111111111000000000000000000000000000000000000000000000000000 8 | 63.high-n-bits is 0b1111111111111111111111111111111111111111111111111111111111111110 9 | 64.high-n-bits is 0b1111111111111111111111111111111111111111111111111111111111111111 10 | 11 | test 12 | 0.low-n-bits is 0 13 | 1.low-n-bits is 1 14 | 13.low-n-bits is 0b1111111111111 15 | 63.low-n-bits is 0b111111111111111111111111111111111111111111111111111111111111111 16 | 64.low-n-bits is 0b1111111111111111111111111111111111111111111111111111111111111111 17 | -------------------------------------------------------------------------------- /license.md: -------------------------------------------------------------------------------- 1 | Source code in this repository is in the public domain. This excludes: 2 | 3 | * `dyncall` and anything in `.gitignore`, which aren't really part of this repository. 4 | * Anything in `site-src/font`. See the readme there for sources. 5 | 6 | If you build with `JIT=1`, executables (e.g. `bin/crow` or `bin/crow-debug`) will link to `libgccjit`. 7 | This uses a GPL license, and so those executables will too. 8 | 9 | The website icon `crow.svg` is from https://openclipart.org/detail/252189/raven-silhouette, where it is public-domain. 10 | 11 | The web site uses fonts: 12 | * Alkatra from https://github.com/suman51284/Alkatra 13 | * Hack from https://github.com/source-foundry/Hack 14 | * Murecho from https://github.com/positype/Murecho-Project 15 | -------------------------------------------------------------------------------- /editor/vscode/readme.md: -------------------------------------------------------------------------------- 1 | # Build 2 | 3 | In the root of the `crow` repository, run `make editor/vscode/crow-0.0.0.vsix`. 4 | 5 | # Install 6 | 7 | First, the extension needs `crow` to be installed somewhere on the default PATH (e.g., `/usr/local/bin/crow`). 8 | See https://crow-lang.org/download.html for instructions. 9 | 10 | Then run: 11 | ``` 12 | code --install-extension crow/editor/vscode/crow-0.0.0.vsix 13 | ``` 14 | 15 | # Debug 16 | 17 | To debug the VSCode extension: 18 | 19 | * Run `code editor/vscode` to open vscode in the directory containing this readme. 20 | * Use Ctrl+Shift+D to open the debugger pane on the left. Click the green arrow to launch the client. 21 | * In the original window, run the command "Output: Focus on Output View". 22 | -------------------------------------------------------------------------------- /src/test/testMap.d: -------------------------------------------------------------------------------- 1 | module test.testMap; 2 | 3 | @safe @nogc pure nothrow: 4 | 5 | import test.testUtil : Test; 6 | import util.col.mutMap : mustAdd, mustDelete, mustGet, MutMap, size; 7 | 8 | void testMap(ref Test test) { 9 | MutMap!(uint, uint) a; 10 | foreach (uint key; [248, 344, 408, 24, 88, 216, 448, 16, 96, 600, 336, 768, 1368, 944, 536, 40, 1432]) { 11 | mustAdd(test.alloc, a, key, key); 12 | validate(a); 13 | } 14 | mustDelete(a, 536); 15 | mustDelete(a, 1368); 16 | validate(a); 17 | } 18 | 19 | private: 20 | 21 | void validate(in MutMap!(uint, uint) a) { 22 | uint count = 0; 23 | foreach (const uint key, ref const uint value; a) { 24 | count++; 25 | assert(mustGet(a, key) == value); 26 | } 27 | assert(size(a) == count); 28 | } 29 | -------------------------------------------------------------------------------- /test/end-to-end/compile-errors/unused.crow: -------------------------------------------------------------------------------- 1 | import 2 | # unused fun 3 | crow/io/duration: second 4 | # unused type 5 | crow/io/time-format: time-locale 6 | # unused type alias 7 | system/unistd: ssize_t 8 | # unused spec 9 | crow/col/collection: begin-end 10 | # unused module 11 | crow/io/process 12 | 13 | main void() 14 | info log "done" 15 | 16 | foo[t] void(p nat, _ string) 17 | _ void mut(x nat) = x => () 18 | _ void mut(x nat) = _ => () 19 | y nat = 2 20 | _ void shared() = shared () => () 21 | () 22 | 23 | -bar[t] void() t compare 24 | () 25 | 26 | -r record mut 27 | r0 -mut nat 28 | 29 | -u union 30 | u0 nat 31 | 32 | -a alias 33 | nat 34 | 35 | -e enum 36 | e0 37 | 38 | -f flags 39 | f0 40 | 41 | -s spec 42 | foo void() 43 | -------------------------------------------------------------------------------- /include/crow/result.crow: -------------------------------------------------------------------------------- 1 | no-std 2 | import 3 | ./bool: bool, false, true 4 | ./compare: equal 5 | ./fun-util: subscript 6 | 7 | ### 8 | A `result` is either a success (`ok`) or failure (`error`) value. 9 | 10 | This provides a more explicit alternative to throwing an exception. 11 | Prefer this over throwing an exception if failure is likely. 12 | ### 13 | +result[ok, error] union(ok ok, error error) 14 | 15 | +==[t, u] bool(a (t, u) result, b (t, u) result) t equal, u equal 16 | 17 | +then[out, in, err] (out, err) result(a (in, err) result, f (out, err) result mut(x in)) 18 | match a 19 | as ok v 20 | f[v] 21 | as error e 22 | e error 23 | 24 | +is-ok[t, u] bool(a (t, u) result) 25 | match a 26 | as ok _ 27 | true 28 | as error _ 29 | false 30 | -------------------------------------------------------------------------------- /test/end-to-end/compile-errors/enum-value-overflow.crow.out: -------------------------------------------------------------------------------- 1 | exit code: 0 2 | stderr: 3 | test/end-to-end/compile-errors/enum-value-overflow.crow 5:9-5:11 A value of type 'nat32' must be from 0 to 4294967295. 4 | test/end-to-end/compile-errors/enum-value-overflow.crow 8:9-8:19 A value of type 'nat32' must be from 0 to 4294967295. 5 | test/end-to-end/compile-errors/enum-value-overflow.crow 10:1-10:2 Type name 'e' is already used. 6 | test/end-to-end/compile-errors/enum-value-overflow.crow 11:9-11:13 A value of type 'int8' must be from -128 to 127. 7 | test/end-to-end/compile-errors/enum-value-overflow.crow 14:9-14:12 A value of type 'int8' must be from -128 to 127. 8 | test/end-to-end/compile-errors/enum-value-overflow.crow 18:9-18:14 A value of type 'nat16' must be from 0 to 65535. 9 | -------------------------------------------------------------------------------- /include/system/dirent.crow: -------------------------------------------------------------------------------- 1 | no-std 2 | import 3 | crow/c-types: err-t 4 | crow/number: int32, nat16 5 | crow/pointer: *, const-pointer, mut-pointer, pointer-cast 6 | crow/string: char8, c-string 7 | system/sys/types: ino_t, off_t 8 | 9 | +DIR extern 10 | 11 | +dirent record extern 12 | d_ino ino_t 13 | d_off off_t 14 | d_reclen nat16 15 | d_type char8 16 | # TODO: d_name char8[256] 17 | -d_name bytes256 18 | -bytes256 extern(256, 1) data 19 | +new dirent() unsafe 20 | 0, 0, 0, "\0", () 21 | 22 | +d_name c-string(a dirent*) unsafe, native extern 23 | (&a->d_name)::bytes256* pointer-cast 24 | 25 | +opendir DIR mut*(name c-string) posix extern 26 | +closedir err-t(dirp DIR mut*) posix extern 27 | +readdir_r int32(dirp DIR mut*, entry dirent mut*, result dirent mut* mut*) posix extern 28 | -------------------------------------------------------------------------------- /site-src/script/util/mutable-observable.crow: -------------------------------------------------------------------------------- 1 | +observable[t] record mut 2 | -observes t mutable-observable 3 | 4 | +get[t] t(a t observable) 5 | a.observes value 6 | 7 | +now-and-subscribe[t] void(a t observable, cb void shared(x t)) 8 | cb[a get] 9 | a subscribe cb 10 | 11 | +subscribe[t] void(a t observable, cb void shared(x t)) 12 | a.observes.subscribers ~= cb 13 | 14 | +mutable-observable[t] record mut 15 | -value mut t 16 | -subscribers void shared(x t) mut[] 17 | 18 | +new[t] t mutable-observable() t new 19 | (), 20 | +new[t] t mutable-observable(initial t) 21 | initial, () 22 | 23 | +observable[t] t observable(a t mutable-observable) 24 | a, 25 | 26 | +set[t] void(a t mutable-observable, value t) 27 | a.value := value 28 | for subscriber : a subscribers 29 | subscriber[value] 30 | -------------------------------------------------------------------------------- /test/unit/globals.crow: -------------------------------------------------------------------------------- 1 | import 2 | crow/io/file: null-path, write-file 3 | 4 | dummy-globals nat() 5 | 0 6 | 7 | test trusted 8 | g := 33 9 | results nat[] = for _ : 0::nat .. 100 parallel 10 | # If 'foo' were thread-local, this would be uninitialized for some threads. 11 | g 12 | results is for _ : 1::nat64 .. 101; 33 13 | results[99] is 33 14 | () 15 | -g global(nat64) 16 | 17 | test summon, trusted, (native, libc) extern 18 | results nat[] = for x : 0::nat64 .. 100 parallel 19 | tl := x 20 | tl +:= 1 21 | # This gives 'foo' time to change before returning, 22 | # which would reliably cause the test to fail if 'foo' were global 23 | null-path write-file "{x}" 24 | tl 25 | results is for x : 1::nat64 .. 101; x 26 | results[99] is 100 27 | () 28 | -tl thread-local(nat64) 29 | -------------------------------------------------------------------------------- /include/crow/test-util.crow: -------------------------------------------------------------------------------- 1 | ### 2 | Functions for use in tests. 3 | ### 4 | 5 | no-std 6 | import 7 | ./compare: equal 8 | ./exception: error, exception 9 | ./json: json, show 10 | ./misc: new, to, void 11 | ./string: interpolate, string 12 | 13 | +expected-equal record(a json, b json) exception variant-member 14 | +show string(a expected-equal) 15 | "Expected {a a} is {a b}" 16 | 17 | ### 18 | Asserts the the values are equal. 19 | ### 20 | +is[t] void(a t, b t) t equal, (json, t) to 21 | assert a == b : a.to expected-equal b.to 22 | 23 | ### 24 | Use this like so: 25 | try 26 | << some code >> 27 | should-throw 28 | catch expected-exception x 29 | << assertions, or just '()' >> 30 | ### 31 | +should-throw void() 32 | throw "Should have thrown a different exception before getting here" error 33 | -------------------------------------------------------------------------------- /include/crow/crypto/random.crow: -------------------------------------------------------------------------------- 1 | ### 2 | Functions for generating cryptographically random numbers. 3 | ### 4 | 5 | import 6 | system/sodium: randombytes_random 7 | ../bits: bits-cat 8 | ../js: call-new, call-property, cast, js-global, subscript 9 | ./private/sodium: ensure-sodium-initialized 10 | ../private/bootstrap: todo 11 | 12 | +random nat32() summon, trusted 13 | if extern native 14 | if extern sodium 15 | ensure-sodium-initialized 16 | randombytes_random 17 | else 18 | todo 19 | elif extern js 20 | xs = "Uint32Array".js-global call-new 1::float64 21 | _ = "crypto".js-global call-property "getRandomValues", xs 22 | xs["0"].cast::float64 to 23 | else 24 | todo 25 | 26 | +random bool() summon 27 | random::nat32 % 2 == 0 28 | 29 | +random nat64() summon 30 | random bits-cat random 31 | -------------------------------------------------------------------------------- /demo/sqlite3/main.crow: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env crow 2 | import 3 | crow/io/file: remove-file 4 | crow/io/print: out, print 5 | crow/parse 6 | sqlite3/main: iterate, open-sqlite3, query, run, size, with-block 7 | 8 | main void() summon, (native, sqlite3) extern 9 | file-name string = "test.db" 10 | with db : file-name open-sqlite3 11 | db run "drop table if exists foo" 12 | db run "create table foo (name varchar(255), quantity int);" 13 | db run "insert into foo (name, quantity) values (\"tomato\", 3), (\"potato\", 7)" 14 | 15 | rows (string, nat64)[] = for row : db query "select * from foo" 16 | name = row["name"]! 17 | quantity = nat parse! row["quantity"]! 18 | name, quantity 19 | 20 | out print ("\n" join for row : rows; "{row a}: {row b}") 21 | db run "drop table foo" 22 | file-name remove-file 23 | () 24 | -------------------------------------------------------------------------------- /demo/server.crow: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env crow 2 | import 3 | crow/io/net/http-server: http-handler, http-server, with-block 4 | crow/io/net/http-types 5 | crow/io/stdin: read-stdin 6 | 7 | main void() summon, native extern 8 | port nat16 = 8080 9 | handler http-handler = req => 10 | descr = req describe-request 11 | info log descr 12 | 200, "OK", (), "Your request:\n{descr}".to-bytes 13 | with _ : port http-server handler 14 | info log "Running at http://localhost:{port}/ ; press enter to stop" 15 | _ = read-stdin 16 | 17 | -describe-request string(a http-request) 18 | headers = "\n" join for k, v : a headers 19 | "{k}: {v}" 20 | "{a method} {a path}{a query}\n{headers}\n\n{a.body as-string}" 21 | 22 | show string(a string[symbol]) 23 | if a is-empty 24 | "" 25 | else 26 | "?" ~~ ("&" join for k, v : a; "{k}={v}") 27 | -------------------------------------------------------------------------------- /test/unit/library/col/set-tests.crow: -------------------------------------------------------------------------------- 1 | import 2 | ../../../../include/crow/col/set: dbg 3 | 4 | dummy-set-tests nat64() 5 | 0 6 | 7 | -verify void(a nat64 set, expected string) 8 | a.dbg is expected 9 | 10 | test 11 | a nat64 set = () 12 | a.is-empty is true 13 | a.size is 0 14 | a verify "[]" 15 | 16 | b = a ~ 5 17 | b.is-empty is false 18 | b.size is 1 19 | b.to::nat64[] is (5,) 20 | b verify "[5]" 21 | 22 | c = b ~~ (6, 4, 1) 23 | c verify "[1 4 6 5]" 24 | 25 | d = c ~ 8 26 | d verify "[1 4 6 5], [8]" 27 | 28 | e = d ~~ (4, 10) 29 | e verify "[1 4 6 5], [10 8]" 30 | e.size is 6 31 | e[0] is false 32 | e[1] is true 33 | e[2] is false 34 | e[3] is false 35 | e[4] is true 36 | e[5] is true 37 | e[6] is true 38 | e[7] is false 39 | e[8] is true 40 | e[9] is false 41 | e[10] is true 42 | e[11] is false 43 | -------------------------------------------------------------------------------- /include/crow/io/terminal-color.crow: -------------------------------------------------------------------------------- 1 | ### 2 | Functions for adding colors to terminal output. 3 | ### 4 | 5 | # Resets any color. 6 | +reset string() 7 | "\x1b[m" 8 | 9 | +term-foreground-color enum 10 | black = 30 11 | red = 31 12 | green = 32 13 | yellow = 33 14 | blue = 34 15 | purple = 35 16 | cyan = 36 17 | white = 37 18 | 19 | # String that when printed, will set the terminal's foreground color. 20 | +foreground string(a term-foreground-color) 21 | "\x1b[{a.to::nat32}m" 22 | 23 | # String that when printed, will set the terminal's foreground color. 24 | +foreground string(red float64, green float64, blue float64) 25 | "\x1b[38;2;{red to-color};{green to-color};{blue to-color}m" 26 | 27 | # String that when printed, will make text bold. 28 | +bold string() 29 | "\x1b[1m" 30 | 31 | -to-color nat8(f float64) 32 | f * 255 to 33 | -------------------------------------------------------------------------------- /include/system/sys/epoll.crow: -------------------------------------------------------------------------------- 1 | no-std 2 | import 3 | crow/c-types: c-int, err-t, fd-t 4 | crow/number: nat32, nat64 5 | crow/pointer: mut-pointer 6 | 7 | +epoll_create1 fd-t(epoll-flags c-int) linux extern 8 | 9 | +epoll_event record(events nat32, event_data nat64) extern, packed 10 | 11 | +new epoll_event() bare 12 | 0, 0 13 | 14 | +epoll_ctl err-t(epfd fd-t, op c-int, fd fd-t, event epoll_event mut*) linux extern 15 | 16 | +epoll_wait err-t( 17 | epfd fd-t, 18 | events epoll_event mut*, 19 | max-events c-int, 20 | timeout c-int, 21 | ) linux extern 22 | 23 | +EPOLLIN nat32() bare 24 | 1 25 | +EPOLLERR nat32() bare 26 | 8 27 | +EPOLLHUP nat32() bare 28 | 0x10 29 | +EPOLLET nat32() bare 30 | 0x80000000 31 | 32 | +EPOLL_CTL_ADD c-int() bare 33 | 1 34 | +EPOLL_CTL_DEL c-int() bare 35 | 2 36 | +EPOLL_CTL_MOD c-int() bare 37 | 3 38 | -------------------------------------------------------------------------------- /test/unit/closures.crow: -------------------------------------------------------------------------------- 1 | dummy-closures nat() 2 | 0 3 | 4 | test 5 | x mut nat = 0 6 | f void mut() = () => 7 | x +:= 1 8 | f[] 9 | x is 1 10 | 11 | test 12 | x mut nat = 0 13 | f void mut() = () => 14 | x +:= 1 15 | g void mut() = () => 16 | x +:= 2 17 | f[] 18 | g[] 19 | x is 3 20 | 21 | test 22 | x mut nat, y mut nat = 1, 2 23 | f void mut() = () => 24 | x +:= 1 25 | y +:= 2 26 | f[] 27 | x is 2 28 | y is 4 29 | 30 | test 31 | try x mut nat = 3 catch divide-by-0 : unreachable 32 | f void mut() = () => 33 | x +:= 2 34 | f[] 35 | x is 5 36 | 37 | test 38 | x mut foo = 0, 39 | get foo mut() = () => 40 | x 41 | set void mut() = () => 42 | x := 1, 43 | get[].x is 0 44 | set[] 45 | get[].x is 1 46 | # Make this by-ref so that the mutable local must use a pointer to pointer 47 | -foo record(x nat) by-ref 48 | -------------------------------------------------------------------------------- /demo/time-format.crow: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env crow 2 | import 3 | crow/io/print: out, print 4 | crow/io/time: get-unix-time 5 | crow/io/time-format: 6 | date, day-of-week-long, gmt, iso-date, iso-timestamp, local-time, time-of-day, 7 | timezone-name, timezone-offset, year 8 | 9 | main void() summon, (native, posix) extern 10 | t = get-unix-time 11 | out print """ 12 | ISO time: {t iso-timestamp} 13 | local timezone: {local-time timezone-name t} 14 | local timezone offset: {local-time timezone-offset t} 15 | year: {gmt year t} 16 | date (UTC): {gmt date t} 17 | date (local): {local-time date t} 18 | date (local in ISO 8601 format): {local-time iso-date t} 19 | time (UTC): {gmt time-of-day t} 20 | time (local): {local-time time-of-day t} 21 | day of week (UTC): {gmt day-of-week-long t} 22 | day of week (local): {local-time day-of-week-long t} 23 | """ 24 | -------------------------------------------------------------------------------- /site-src/search-dir-recursive.crow: -------------------------------------------------------------------------------- 1 | import 2 | crow/io/file: is-directory, names-in-dir 3 | crow/io/path: child-path 4 | 5 | search-dir-recursive string[](path string) summon, native extern 6 | path search-dir-recursive _ => true 7 | 8 | search-dir-recursive string[]( 9 | path string, 10 | file-filter bool shared(file-name string), 11 | ) summon, native extern 12 | path search-dir-recursive (_ => true), file-filter 13 | 14 | search-dir-recursive string[]( 15 | path string, 16 | dir-filter bool shared(dir-name string), 17 | file-filter bool shared(file-name string), 18 | ) summon, native extern 19 | for name : path.names-in-dir parallel-concat 20 | child = path child-path name 21 | if child is-directory 22 | if dir-filter[name] 23 | child search-dir-recursive dir-filter, file-filter 24 | elif file-filter[name] 25 | child, 26 | -------------------------------------------------------------------------------- /test/unit/library/exclusion-queue-tests.crow: -------------------------------------------------------------------------------- 1 | import 2 | ../../../include/crow/private/exclusion-queue 3 | 4 | dummy-exclusion-queue-tests nat() 5 | 0 6 | 7 | -eq record nominal 8 | -with-block void(_ eq, cb void mut(queue string exclusion-queue mut*)) unsafe, native extern 9 | queue mut string exclusion-queue = uninit 10 | a string exclusion-queue mut* = &queue 11 | a init 12 | finally a destroy 13 | cb[a] 14 | 15 | test trusted, native extern 16 | with a : eq 17 | a.dequeue is () 18 | a enqueue 0, "a" 19 | a.dequeue is ((0, "a"),) 20 | a.dequeue is () 21 | a release-exclusion 0 22 | 23 | test trusted, native extern 24 | with a : eq 25 | a.dequeue is () 26 | a enqueue 0, "a" 27 | a.dequeue is ((0, "a"),) 28 | a.dequeue is () 29 | a enqueue 0, "b" 30 | a.dequeue is () 31 | a release-exclusion 0 32 | a.dequeue is ((0, "b"),) 33 | -------------------------------------------------------------------------------- /include/crow/io/environ.crow: -------------------------------------------------------------------------------- 1 | import 2 | system/unistd: __environ 3 | ../private/c-string-util: find-char-in-c-string, find-c-string-end 4 | 5 | get-environ-raw c-string*() summon, unsafe 6 | __environ 7 | 8 | # Get all environment variables for this process. 9 | +get-environ string[string]() summon, native extern 10 | forbid trusted extern windows : todo 11 | with out : build 12 | trusted 13 | env mut = get-environ-raw 14 | until *env == null 15 | out ~= env->parse-environ-entry 16 | env +:= 1 17 | 18 | -parse-environ-entry (string, string)(entry c-string) unsafe, native extern 19 | assert key-end ?= entry find-char-in-c-string "=" : todo 20 | key string = (entry .. key-end).as-array to 21 | value-begin = key-end + 1 22 | value-end = value-begin find-c-string-end 23 | value string = (value-begin .. value-end).as-array to 24 | key, value 25 | -------------------------------------------------------------------------------- /test/end-to-end/compile-errors/extern-errors.crow: -------------------------------------------------------------------------------- 1 | main void() 2 | () 3 | 4 | r record extern 5 | a string 6 | b nat array 7 | c string array 8 | 9 | r2 record by-val, extern 10 | a nat64 11 | 12 | r3 record by-ref, extern 13 | a nat64 14 | 15 | u union extern 16 | a string 17 | 18 | f void() extern 19 | 20 | f void() libc extern 21 | 22 | f string() libc extern 23 | 24 | f void(a string) libc extern 25 | 26 | f[t] void(a t) libc extern 27 | 28 | f void(...a nat64 array) libc extern 29 | 30 | some-spec spec 31 | foo void() 32 | 33 | f void() libc extern, some-spec 34 | 35 | f void() bare, libc extern 36 | 37 | f void() unsafe, libc extern 38 | 39 | g global(nat) libc extern 40 | 41 | g global(nat) 42 | 43 | g2 global(nat) builtin, libc extern 44 | 45 | g3 global(nat) extern, bare, nat equal 46 | 47 | tl thread-local(nat) libc extern, nat equal 48 | -------------------------------------------------------------------------------- /src/test/testSymbolSet.d: -------------------------------------------------------------------------------- 1 | module test.testSymbolSet; 2 | 3 | @safe @nogc pure nothrow: 4 | 5 | import test.testUtil : Test; 6 | import util.symbol : Symbol, symbol; 7 | import util.symbolSet : emptySymbolSet, SymbolSet, symbolSet; 8 | 9 | void testSymbolSet(ref Test test) { 10 | assert(symbol!"" !in emptySymbolSet); 11 | 12 | Symbol a = symbol!"a"; 13 | Symbol b = symbol!"b"; 14 | Symbol c = symbol!"c"; 15 | 16 | SymbolSet setA = symbolSet(a); 17 | assert(a in setA); 18 | assert(b !in setA); 19 | 20 | SymbolSet setB = symbolSet(b); 21 | assert(b in setB); 22 | assert(a !in setB); 23 | 24 | SymbolSet setAB = setA | b; 25 | assert(a in setAB); 26 | assert(b in setAB); 27 | assert(c !in setAB); 28 | assert(setAB.containsAll(setA)); 29 | assert(!setA.containsAll(setAB)); 30 | 31 | assert((setB | a) == setAB); 32 | assert((setB | setA) == setAB); 33 | } 34 | -------------------------------------------------------------------------------- /test/unit/auto-funs.crow: -------------------------------------------------------------------------------- 1 | dummy-auto-funs nat() 2 | 0 3 | 4 | -r record 5 | x nat 6 | y string 7 | -== bool(a r, b r) 8 | -<=> comparison(a r, b r) 9 | -to json(a r) 10 | 11 | test 12 | r0 r = 1, "two" 13 | r1 r = 1, "three" 14 | r0 is r0 15 | forbid r0 == r1 16 | r0 <=> r0 is equal 17 | r0 <=> r1 is greater 18 | r1 <=> r0 is less 19 | r0.to::json is (("x", 1::nat.to), ("y", "two"::string.to)) 20 | 21 | -u union 22 | x nat 23 | y string 24 | -== bool(a u, b u) 25 | -<=> comparison(a u, b u) 26 | -to json(a u) 27 | 28 | test 29 | u0 u = 1 x 30 | u1 u = "two" y 31 | u0 is u0 32 | forbid u0 == u1 33 | u0 <=> u0 is equal 34 | u0 <=> 0.x is greater 35 | u0 <=> 2.x is less 36 | u0 <=> u1 is less 37 | u1 <=> u0 is greater 38 | u1 <=> "twn".y is greater 39 | u1 <=> "twp".y is less 40 | u0.to::json is (("x", 1::nat.to),) 41 | u1.to::json is (("y", "two"::string.to),) 42 | -------------------------------------------------------------------------------- /test/unit/library/col/map-tests.crow: -------------------------------------------------------------------------------- 1 | import 2 | ../../../../include/crow/col/map: dbg 3 | 4 | dummy-map-tests nat64() 5 | 0 6 | 7 | verify void(a string[nat64], expected string) 8 | a.dbg is expected 9 | 10 | test 11 | l0 string[nat64] = () 12 | l0.is-empty is true 13 | l0.size is 0 14 | l0 verify "[]" 15 | l0[0] is () 16 | 17 | l1 = l0 ~ (5, "5") 18 | l1.is-empty is false 19 | l1.size is 1 20 | l1 verify "[5 -> 5]" 21 | 22 | l2 = l1 ~~ ((1, "1"), (3, "3"), (9, "9")) 23 | l2 verify "[5 -> 5, 1 -> 1, 3 -> 3, 9 -> 9]" 24 | 25 | l3 = l2 ~ (13, "13") 26 | l3 verify "[5 -> 5, 1 -> 1, 3 -> 3, 9 -> 9, 13 -> 13]" 27 | #l3 verify "1[1 -> 1, 9 -> 9] 3[3 -> 3] 5[13 -> 13, 5 -> 5]" 28 | 29 | #l3[3] is ("3",) 30 | #l3[4] is () 31 | 32 | #l3 - 3 verify "[1 -> 1, 9 -> 9, 13 -> 13, 5 -> 5]" 33 | 34 | # TODO: lots more tests. Be sure to test removal can remove inner nodes. 35 | -------------------------------------------------------------------------------- /demo/libraries/audio/audio.crow: -------------------------------------------------------------------------------- 1 | import 2 | ./sound: sound, sound-format 3 | 4 | +audio record shared 5 | format sound-format 6 | clear void shared() 7 | play playing-sound shared(x sound) 8 | play-loop playing-sound shared(x sound) 9 | shut-down void shared() 10 | 11 | +playing-sound record shared 12 | reset-position void shared() 13 | # NOTE: This doesn't reset the sound's position 14 | set-playing void shared(should-be-playing bool) 15 | 16 | # Also known as 'pause' 17 | +pause void(a playing-sound) 18 | a set-playing false 19 | 20 | +stop void(a playing-sound) 21 | a set-playing false 22 | a reset-position 23 | 24 | ### 25 | WARN: This doesn't reset the sound's position. 26 | If it's already over, this has no effect. 27 | ### 28 | +resume void(a playing-sound) 29 | a set-playing true 30 | 31 | +restart void(a playing-sound) 32 | a reset-position 33 | a set-playing true 34 | -------------------------------------------------------------------------------- /demo/open-gl/fragment.frag.essl: -------------------------------------------------------------------------------- 1 | #version 300 es 2 | 3 | #ifdef GL_ES 4 | precision highp float; 5 | #endif 6 | 7 | smooth in vec3 normal; 8 | smooth in vec3 color; 9 | smooth in vec2 texCoord; 10 | out vec4 fragColor; 11 | 12 | uniform sampler2D texSampler; 13 | 14 | vec4 applyLight(const float l, const vec4 c) { 15 | return vec4(c.r * l, c.g * l, c.b * l, c.a); 16 | } 17 | 18 | vec4 mixColor(const vec3 color, const vec4 c) { 19 | return vec4(color.r * c.r, color.g * c.g, color.b * c.b, c.a); 20 | } 21 | 22 | void main() { 23 | const vec3 lightDirection = normalize(vec3(-1, -1, 1)); 24 | const float lightIntensity = 2.0; 25 | const float ambientLight = 0.33; 26 | float lightAmount = ambientLight + lightIntensity * max(dot(-lightDirection, normal), 0.0); 27 | vec4 texColor = mixColor(color, texture(texSampler, texCoord)); 28 | fragColor = applyLight(lightAmount, texColor); 29 | } 30 | -------------------------------------------------------------------------------- /include/crow/io/win32-util.crow: -------------------------------------------------------------------------------- 1 | no-std 2 | import 3 | ../bits: | 4 | ../col/array: subscript 5 | ../col/mut-slice: begin-pointer, cast-immutable, gc-safe-mut-slice, mut-slice, size 6 | ../number: ==, <=>, to 7 | ../pointer: null 8 | ../range: .. 9 | ../string: char8, interpolate, show, string, to 10 | system/win32: 11 | DWORD, FormatMessageA, FORMAT_MESSAGE_FROM_SYSTEM, FORMAT_MESSAGE_IGNORE_INSERTS, 12 | LANG_NEUTRAL, MAKELANGID, SUBLANG_NEUTRAL 13 | 14 | show-win32-error string(err DWORD) summon, unsafe, (native, windows) extern 15 | res char8 mut-slice = 1024 gc-safe-mut-slice 16 | fmt = FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS 17 | lid = LANG_NEUTRAL MAKELANGID SUBLANG_NEUTRAL 18 | size = fmt FormatMessageA null, err, lid, res.begin-pointer, res.size.to, null 19 | if size == 0 20 | "<>" 21 | else 22 | res.cast-immutable[0 .. size.to] to 23 | -------------------------------------------------------------------------------- /test/end-to-end/runnable/gc.crow: -------------------------------------------------------------------------------- 1 | import 2 | crow/io/print: out, print 3 | crow/private/alloc: gc-stats, get-gc, get-stats, force-needs-gc, set-hard-limit 4 | 5 | main void() summon, trusted, native extern 6 | gc = get-gc 7 | # To speed up 'gc.get-stats' 8 | gc.hard-limit := 0x40000 9 | 10 | # We'll keep one alive, but not the second 11 | a r = 1, 2, 3 12 | _ r = 4, 5, 6 13 | 14 | out print "stats: {gc get-stats}" 15 | out print "a: {a}" 16 | out print "stats (after print): {gc get-stats}" 17 | 18 | gc force-needs-gc 19 | yield-fiber 20 | 21 | out print "-- after gc --" 22 | out print "stats: {gc get-stats}" 23 | out print "a: {a}" 24 | out print "stats (after print): {gc get-stats}" 25 | () 26 | 27 | -r record by-ref 28 | a nat 29 | b nat 30 | c nat 31 | -show string(a r) 32 | "a={a a}, b={a b}, c={a c}" 33 | 34 | -show string(a gc-stats) 35 | a.to::json show 36 | -to json(a gc-stats) 37 | -------------------------------------------------------------------------------- /include/system/sodium.crow: -------------------------------------------------------------------------------- 1 | import 2 | crow/c-types: err-t, size_t, u-long-long 3 | 4 | +sodium_init err-t() sodium extern, pure 5 | 6 | +crypto_pwhash_strbytes size_t() sodium extern, pure 7 | 8 | +crypto_pwhash_opslimit_moderate size_t() sodium extern, pure 9 | +crypto_pwhash_opslimit_sensitive size_t() sodium extern, pure 10 | +crypto_pwhash_memlimit_moderate size_t() sodium extern, pure 11 | +crypto_pwhash_memlimit_sensitive size_t() sodium extern, pure 12 | 13 | +crypto_pwhash_str err-t( 14 | # Length should be crypto_pwhash_strbytes 15 | output char8 mut*, 16 | passwd c-string, 17 | passwdlen u-long-long, 18 | opslimit u-long-long, 19 | memlimit size_t, 20 | ) sodium extern, pure 21 | 22 | +crypto_pwhash_str_verify err-t( 23 | # Length should be crypto_pwhash_strbytes 24 | str char8*, 25 | passwd c-string, 26 | passwdlen u-long-long, 27 | ) sodium extern, pure 28 | 29 | +randombytes_random nat32() sodium extern 30 | -------------------------------------------------------------------------------- /test/unit/library/all.crow: -------------------------------------------------------------------------------- 1 | import 2 | ./col/all: dummy-col-tests 3 | ./bare-map-tests: dummy-bare-map-tests 4 | ./bare-queue-tests: dummy-bare-queue-tests 5 | ./bits-tests: dummy-bits-tests 6 | ./exclusion-queue-tests: dummy-exclusion-queue-tests 7 | ./json-tests: dummy-json-tests 8 | ./math-tests: dummy-math-tests 9 | ./number-tests: dummy-number-tests 10 | ./shared-array-tests: dummy-shared-array-tests 11 | ./shared-map-tests: dummy-shared-map-tests 12 | ./string-tests: dummy-string-tests 13 | ./symbol-tests: dummy-symbol-tests 14 | 15 | dummy-library-tests nat() 16 | _ = dummy-bare-map-tests 17 | _ = dummy-bare-queue-tests 18 | _ = dummy-bits-tests 19 | _ = dummy-col-tests 20 | _ = dummy-exclusion-queue-tests 21 | _ = dummy-json-tests 22 | _ = dummy-math-tests 23 | _ = dummy-number-tests 24 | _ = dummy-shared-array-tests 25 | _ = dummy-shared-map-tests 26 | _ = dummy-string-tests 27 | _ = dummy-symbol-tests 28 | -------------------------------------------------------------------------------- /test/unit/library/string-tests.crow: -------------------------------------------------------------------------------- 1 | import 2 | crow/math/math: pi 3 | 4 | dummy-string-tests nat64() 5 | 0 6 | 7 | test 8 | c8s char8[] = "$¥₿𝄮" 9 | c32s char32[] = "$¥₿𝄮" 10 | s string = "$¥₿𝄮" 11 | 12 | c8s.to::string is s 13 | s.to::char8[] is c8s 14 | c32s.to::string is s 15 | s.to::char32[] is c32s 16 | 17 | s.reverse is "𝄮₿¥$" 18 | "\ue000"::string.to::char32[] is "\ue000" 19 | "\ue000"::char32[].to::string is "\ue000" 20 | 21 | test 22 | 3::float64.show is "3" 23 | 12.3::float64.show is "12.3" 24 | 0.04::float64.show is "0.04" 25 | 0.123::float64.show is "0.123" 26 | 0.001::float64.show is "0.001" 27 | 3.14159::float64.show is "3.14159" 28 | pi::float64.show is "3.141592653589794" 29 | 30 | infinity::float64.show is "Infinity" 31 | (-infinity)::float64.show is "-Infinity" 32 | (trusted nan)::float64.show is "NaN" 33 | 34 | test 35 | "a\nb".lines is ("a", "b") 36 | "a\r\nb".lines is ("a", "b") 37 | -------------------------------------------------------------------------------- /include/crow/flags-util.crow: -------------------------------------------------------------------------------- 1 | no-std 2 | import 3 | ./bool: bool 4 | ./col/array: ~=, array, build, iterate, size 5 | ./col/collection: build, for-loop, with-block 6 | ./compare: equal 7 | ./json: json, to 8 | ./misc: new 9 | ./string: join, string 10 | ./symbol: symbol, to 11 | 12 | +flags-like[t] spec t equal 13 | & t(a t, b t) 14 | | t(a t, b t) 15 | flags-members (symbol, t)[]() 16 | 17 | ### 18 | True if every flag set in `a` is set in `b`. 19 | ### 20 | +is-in[t] bool(a t, b t) bare, t flags-like 21 | a & b == a 22 | 23 | # Returns the names of every flag set in `a`. 24 | +to[t] symbol[](a t) t flags-like 25 | with out : build 26 | for name, value : flags-members 27 | if value is-in a 28 | out ~= name 29 | 30 | # Flag names separated by `|`, like `"foo | bar"`. 31 | +to[t] string(a t) t flags-like 32 | " | " join for x : a.to::symbol[]; x to 33 | 34 | +to[t] json(a t) t flags-like 35 | a.to::symbol[] to 36 | -------------------------------------------------------------------------------- /test/end-to-end/compile-errors/spec-inst-recursion.crow.out: -------------------------------------------------------------------------------- 1 | exit code: 1 2 | stderr: 3 | test/end-to-end/compile-errors/spec-inst-recursion.crow 2:16-2:19 Spec instantiation is too deep. 4 | Calling: 5 | foo@string (from test/end-to-end/compile-errors/spec-inst-recursion.crow line 10) 6 | bar@string (from test/end-to-end/compile-errors/spec-inst-recursion.crow line 13) 7 | foo@string (from test/end-to-end/compile-errors/spec-inst-recursion.crow line 10) 8 | bar@string (from test/end-to-end/compile-errors/spec-inst-recursion.crow line 13) 9 | foo@string (from test/end-to-end/compile-errors/spec-inst-recursion.crow line 10) 10 | bar@string (from test/end-to-end/compile-errors/spec-inst-recursion.crow line 13) 11 | foo@string (from test/end-to-end/compile-errors/spec-inst-recursion.crow line 10) 12 | bar@string (from test/end-to-end/compile-errors/spec-inst-recursion.crow line 13) 13 | Uncaught exception: Reached compile error 14 | at main 15 | -------------------------------------------------------------------------------- /demo/libraries/SDL2/SDL_surface.crow: -------------------------------------------------------------------------------- 1 | import 2 | crow/c-types: c-int 3 | ./SDL_pixels: SDL_PixelFormat 4 | ./SDL_rect: SDL_Rect 5 | ./SDL_rwops: SDL_RWFromFile, SDL_RWops 6 | 7 | +SDL_FreeSurface void(surface SDL_Surface mut*) SDL2 extern 8 | 9 | +SDL_Surface record extern, mut 10 | surface-flags nat32 11 | format SDL_PixelFormat mut* 12 | w c-int 13 | h c-int 14 | pitch c-int 15 | pixels any-mut-pointer 16 | userdata any-mut-pointer 17 | locked c-int 18 | list_blitmap any-mut-pointer 19 | clip_rect SDL_Rect 20 | # TODO: SDL_BlitMap 21 | map any-mut-pointer 22 | refcount c-int 23 | 24 | +SDL_LoadBMP_RW SDL_Surface mut*(src SDL_RWops mut*, freesrc c-int) SDL2 extern 25 | 26 | +SDL_LoadBMP SDL_Surface mut*(file string) summon, unsafe, (native, SDL2) extern 27 | file.to SDL_RWFromFile "rb" SDL_LoadBMP_RW 1 28 | 29 | +SDL_ConvertSurfaceFormat SDL_Surface mut*( 30 | src SDL_Surface mut*, 31 | pixel_format nat32, 32 | flags_ nat32, 33 | ) SDL2 extern 34 | -------------------------------------------------------------------------------- /include/system/poll.crow: -------------------------------------------------------------------------------- 1 | no-std 2 | import 3 | crow/bits: bits-intersect 4 | crow/bool: bool 5 | crow/c-types: fd-t, u-long 6 | crow/number: int16, int32 7 | crow/pointer: mut-pointer 8 | 9 | +pollfd record(fd fd-t, events int16, revents int16) extern 10 | 11 | +POLLIN int16() 12 | 1 13 | +POLLPRI int16() 14 | 2 15 | +POLLOUT int16() 16 | 4 17 | +POLLERR int16() 18 | 8 19 | +POLLHUP int16() 20 | 0x10 21 | +POLLNVAL int16() 22 | 0x20 23 | 24 | +poll int32(fds pollfd mut*, nfds u-long, timeout int32) libc extern 25 | 26 | +has-POLLIN bool(revents int16) 27 | revents bits-intersect POLLIN 28 | +has-POLLPRI bool(revents int16) 29 | revents bits-intersect POLLPRI 30 | +has-POLLOUT bool(revents int16) 31 | revents bits-intersect POLLOUT 32 | +has-POLLERR bool(revents int16) 33 | revents bits-intersect POLLERR 34 | +has-POLLHUP bool(revents int16) 35 | revents bits-intersect POLLHUP 36 | +has-POLLNVAL bool(revents int16) 37 | revents bits-intersect POLLNVAL 38 | -------------------------------------------------------------------------------- /test/end-to-end/compile-errors/auto-fun-flags.crow.out: -------------------------------------------------------------------------------- 1 | exit code: 0 2 | stdout: 3 | info: true 4 | stderr: 5 | test/end-to-end/compile-errors/auto-fun-flags.crow 10:1-10:3 A 'bare' function can't call non-'bare' function '== bool(a foo, b foo)' (from test/end-to-end/compile-errors/auto-fun-flags.crow line 13). 6 | test/end-to-end/compile-errors/auto-fun-flags.crow 10:1-10:3 A non-'unsafe' function can't call 'unsafe' function '== bool(a foo, b foo)' (from test/end-to-end/compile-errors/auto-fun-flags.crow line 13). 7 | (Consider putting the call in a 'trusted' expression.) 8 | test/end-to-end/compile-errors/auto-fun-flags.crow 10:1-10:3 A 'bare' function can't call non-'bare' function '== bool(a bar, b bar)' (from test/end-to-end/compile-errors/auto-fun-flags.crow line 16). 9 | test/end-to-end/compile-errors/auto-fun-flags.crow 10:1-10:3 A non-'summon' function can't call 'summon' function '== bool(a bar, b bar)' (from test/end-to-end/compile-errors/auto-fun-flags.crow line 16). 10 | -------------------------------------------------------------------------------- /test/end-to-end/compile-errors/function-pointer-not-supported.crow.out: -------------------------------------------------------------------------------- 1 | exit code: 1 2 | stderr: 3 | test/end-to-end/compile-errors/function-pointer-not-supported.crow 2:26-2:29 Cannot choose an overload of 'foo'. Multiple functions match: 4 | 'foo void()' (from test/end-to-end/compile-errors/function-pointer-not-supported.crow line 13) 5 | 'foo void()' (from test/end-to-end/compile-errors/function-pointer-not-supported.crow line 15) 6 | test/end-to-end/compile-errors/function-pointer-not-supported.crow 3:26-3:29 Can't infer type arguments to 'goo[t] void()' (from test/end-to-end/compile-errors/function-pointer-not-supported.crow line 18) 7 | test/end-to-end/compile-errors/function-pointer-not-supported.crow 4:25-4:33 Function pointer expression must be a plain identifier ('&f'). 8 | test/end-to-end/compile-errors/function-pointer-not-supported.crow 10:28-10:32 The target of a function pointer must be a 'bare' function. 9 | Uncaught exception: Reached compile error 10 | at main 11 | -------------------------------------------------------------------------------- /test/end-to-end/compile-errors/spec-use-invalid.crow.out: -------------------------------------------------------------------------------- 1 | exit code: 0 2 | stderr: 3 | test/end-to-end/compile-errors/spec-use-invalid.crow 4:18-4:25 A builtin type can't have specs. 4 | test/end-to-end/compile-errors/spec-use-invalid.crow 6:3-6:4 An enum type can't have type parameters. 5 | test/end-to-end/compile-errors/spec-use-invalid.crow 6:14-6:21 An enum type can't have specs. 6 | test/end-to-end/compile-errors/spec-use-invalid.crow 8:4-8:5 An extern type can't have type parameters. 7 | test/end-to-end/compile-errors/spec-use-invalid.crow 8:14-8:21 An extern type can't have specs. 8 | test/end-to-end/compile-errors/spec-use-invalid.crow 10:3-10:4 A flags type can't have type parameters. 9 | test/end-to-end/compile-errors/spec-use-invalid.crow 10:12-10:19 A flags type can't have specs. 10 | test/end-to-end/compile-errors/spec-use-invalid.crow 12:13-12:20 A record type can't have specs. 11 | test/end-to-end/compile-errors/spec-use-invalid.crow 14:15-14:22 A union type can't have specs. 12 | -------------------------------------------------------------------------------- /test/end-to-end/parse-errors/string-escape-invalid.crow.out: -------------------------------------------------------------------------------- 1 | exit code: 0 2 | stdout: 3 | info: q is � 4 | info: x is � 5 | info: xit is �it 6 | info: uf00l! is �l! 7 | info: d7ff is ퟿ 8 | info: d800 is � 9 | info: dfff is � 10 | info: e000 is  11 | info: 0010ffff is 􏿿 12 | info: 00110000 is � 13 | stderr: 14 | test/end-to-end/parse-errors/string-escape-invalid.crow 2:20-2:22 Invalid escape sequence '\q'. 15 | test/end-to-end/parse-errors/string-escape-invalid.crow 3:20-3:22 Invalid escape sequence '\x'. 16 | test/end-to-end/parse-errors/string-escape-invalid.crow 4:22-4:24 Invalid escape sequence '\x'. 17 | test/end-to-end/parse-errors/string-escape-invalid.crow 5:25-5:30 Invalid escape sequence '\uf00'. 18 | test/end-to-end/parse-errors/string-escape-invalid.crow 7:23-7:29 Invalid escape sequence '\ud800'. 19 | test/end-to-end/parse-errors/string-escape-invalid.crow 8:23-8:29 Invalid escape sequence '\udfff'. 20 | test/end-to-end/parse-errors/string-escape-invalid.crow 11:27-11:37 Invalid escape sequence '\U00110000'. 21 | -------------------------------------------------------------------------------- /demo/extern/SDL2/COPYING.txt: -------------------------------------------------------------------------------- 1 | 2 | Simple DirectMedia Layer 3 | Copyright (C) 1997-2020 Sam Lantinga 4 | 5 | This software is provided 'as-is', without any express or implied 6 | warranty. In no event will the authors be held liable for any damages 7 | arising from the use of this software. 8 | 9 | Permission is granted to anyone to use this software for any purpose, 10 | including commercial applications, and to alter it and redistribute it 11 | freely, subject to the following restrictions: 12 | 13 | 1. The origin of this software must not be misrepresented; you must not 14 | claim that you wrote the original software. If you use this software 15 | in a product, an acknowledgment in the product documentation would be 16 | appreciated but is not required. 17 | 2. Altered source versions must be plainly marked as such, and must not be 18 | misrepresented as being the original software. 19 | 3. This notice may not be removed or altered from any source distribution. 20 | 21 | -------------------------------------------------------------------------------- /include/system/sys/wait.crow: -------------------------------------------------------------------------------- 1 | no-std 2 | import 3 | crow/bits: &, >>, bits-intersect 4 | crow/bool: &&, bool 5 | crow/compare: != 6 | crow/number: ==, int32 7 | crow/pointer: mut-pointer 8 | ./types: pid_t 9 | 10 | +waitpid pid_t(pid pid_t, wait-status status-t mut*, options int32) posix extern 11 | 12 | +status-t alias 13 | int32 14 | 15 | +WTERMSIG status-t(status status-t) 16 | # /usr/include/x86_64-linux-gnu/bits/waitstatus.h 17 | status & 0x7f 18 | 19 | +WEXITSTATUS status-t(status status-t) 20 | # /usr/include/x86_64-linux-gnu/bits/waitstatus.h 21 | (status & 0xff00) >> 8 22 | 23 | +WIFEXITED bool(status status-t) 24 | # /usr/include/x86_64-linux-gnu/bits/waitstatus.h 25 | status.WTERMSIG == 0 26 | 27 | +WIFSIGNALED bool(status status-t) 28 | ts = status WTERMSIG 29 | ts != 0 && ts != 0x7f 30 | 31 | +WCOREDUMP bool(status status-t) 32 | status bits-intersect 0x80 33 | 34 | +WIFSTOPPED bool(status status-t) 35 | status & 0xff == 0x7f 36 | 37 | +WIFCONTINUED bool(status status-t) 38 | status == 0xffff 39 | -------------------------------------------------------------------------------- /site-src/script/index.crow: -------------------------------------------------------------------------------- 1 | import 2 | crow/js: as-js, call-property, ==, null, set-subscript 3 | crow/js/dom: query-all 4 | ./crow: make-crow-server 5 | ./crow-runnable: define-crow-runnable-custom-element 6 | ./crow-text: define-crow-text-custom-element 7 | ./icon: define-icon-custom-element 8 | ./loading-spinner: define-loading-spinner-element 9 | ./syntax-translate: define-syntax-translate-element 10 | 11 | main void() summon, js extern 12 | crow = make-crow-server 13 | open-details-on-click 14 | define-icon-custom-element 15 | crow define-crow-runnable-custom-element 16 | define-crow-text-custom-element 17 | define-loading-spinner-element 18 | crow define-syntax-translate-element 19 | 20 | -open-details-on-click void() summon, trusted, js extern 21 | for details : "details" query-all 22 | link = details.as-js call-property "querySelector", "a"::string 23 | unless link == null 24 | fn void mut() = () => 25 | _ = details.as-js call-property "setAttribute", "open"::string, true 26 | link["onclick"] := fn 27 | -------------------------------------------------------------------------------- /src/util/col/mapBuilder.d: -------------------------------------------------------------------------------- 1 | module util.col.mapBuilder; 2 | 3 | @safe @nogc pure nothrow: 4 | 5 | import util.alloc.alloc : Alloc; 6 | import util.col.mutMap : getOrAddAndDidAdd, moveToMap, MutMap, ValueAndDidAdd; 7 | import util.col.map : Map; 8 | import util.opt : has, none, Opt, some; 9 | 10 | struct MapBuilder(K, V) { 11 | @disable this(ref const MapBuilder); 12 | 13 | private: 14 | MutMap!(K, V) builder; 15 | } 16 | 17 | void mustAddToMap(K, V)(ref Alloc alloc, ref MapBuilder!(K, V) a, immutable K key, immutable V value) { 18 | Opt!V res = tryAddToMap(alloc, a, key, value); 19 | assert(!has(res)); 20 | } 21 | 22 | // If there is already a value there, does nothing and returns it 23 | Opt!V tryAddToMap(K, V)(ref Alloc alloc, ref MapBuilder!(K, V) a, immutable K key, immutable V value) { 24 | ValueAndDidAdd!V v = getOrAddAndDidAdd!(K, V)(alloc, a.builder, key, () => value); 25 | return v.didAdd ? none!V : some(v.value); 26 | } 27 | 28 | Map!(K, V) finishMap(K, V)( 29 | ref Alloc alloc, 30 | ref MapBuilder!(K, V) a, 31 | ) => 32 | moveToMap!(K, V)(alloc, a.builder); 33 | -------------------------------------------------------------------------------- /test/unit/flags-tests.crow: -------------------------------------------------------------------------------- 1 | dummy-flags nat() 2 | 0 3 | 4 | test 5 | none f = () 6 | none.to::nat32 is 0 7 | x.to::nat32 is 1 8 | y.to::nat32 is 0b10 9 | z.to::nat32 is 0b100 10 | xy = x | y 11 | xy.to::nat32 is 0b11 12 | xz = x | z 13 | xz.to::nat32 is 0b101 14 | yz = y | z 15 | yz.to::nat32 is 0b110 16 | all = x | y | z 17 | all.to::nat32 is 0b111 18 | 19 | flags-members::(symbol, f)[] is (("x", x), ("y", y), ("z", z)) 20 | 21 | none | none is none 22 | x | x is x 23 | xy | yz is all 24 | all | x is all 25 | 26 | x & yz is none 27 | x & all is x 28 | xy & yz is y 29 | 30 | assert x is-in x 31 | assert x is-in xz 32 | forbid y is-in xz 33 | 34 | none.to::string is "" 35 | x.to::string is "x" 36 | xy.to::string is "x | y" 37 | all.to::string is "x | y | z" 38 | 39 | none.to::json is ()::json[].to 40 | x.to::json is ("x"::string.to,).list 41 | xy.to::json is ("x"::string.to, "y"::string.to).list 42 | 43 | ~none is all 44 | ~x is yz 45 | ~y is xz 46 | ~z is xy 47 | ~xy is z 48 | ~xz is y 49 | ~yz is x 50 | ~all is none 51 | 52 | -f flags(x, y, z) 53 | -------------------------------------------------------------------------------- /src/util/col/mutIndexMap.d: -------------------------------------------------------------------------------- 1 | module util.col.mutIndexMap; 2 | 3 | @safe @nogc pure nothrow: 4 | 5 | import util.alloc.alloc : Alloc; 6 | import util.col.array : fillArray; 7 | import util.memory : overwriteMemory; 8 | import util.opt : force, has, MutOpt, noneMut, someMut; 9 | 10 | struct MutIndexMap(K, V) { 11 | private MutOpt!V[] values_; 12 | 13 | ref const(MutOpt!V) opIndex(immutable K key) const => 14 | values_[key.index]; 15 | } 16 | 17 | MutIndexMap!(K, V) newMutIndexMap(K, V)(ref Alloc alloc, size_t size) => 18 | MutIndexMap!(K, V)(fillArray!(MutOpt!V)(alloc, size, noneMut!V)); 19 | 20 | ref const(V) mustGet(K, V)(ref const MutIndexMap!(K, V) a, immutable K key) => 21 | force(getAt(a, key)); 22 | 23 | V getOrAdd(K, V)( 24 | ref MutIndexMap!(K, V) a, 25 | immutable K key, 26 | in V delegate() @safe @nogc pure nothrow getValue, 27 | ) { 28 | size_t index = key.index; 29 | if (has(a.values_[index])) 30 | return force(a.values_[index]); 31 | else { 32 | V value = getValue(); 33 | overwriteMemory!(MutOpt!V)(&a.values_[index], someMut!V(value)); 34 | return value; 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /demo/libraries/SDL2/SDL_audio.crow: -------------------------------------------------------------------------------- 1 | import 2 | crow/c-types: c-int 3 | 4 | +SDL_AudioFormat alias 5 | nat16 6 | 7 | +AUDIO_F32 SDL_AudioFormat() bare 8 | 0x8120 9 | 10 | +SDL_AudioDeviceID alias 11 | nat32 12 | 13 | +SDL_AudioCallback alias 14 | void function(userdata any-mut-pointer, stream nat8 mut*, len c-int) 15 | 16 | +SDL_AudioSpec record extern, mut 17 | freq c-int 18 | format SDL_AudioFormat 19 | channels nat8 20 | silence nat8 21 | samples nat16 22 | padding nat16 23 | size nat32 24 | callback SDL_AudioCallback 25 | userdata any-mut-pointer 26 | 27 | +new SDL_AudioSpec() bare, unsafe, native extern 28 | 0, 0, 0, 0, 0, 0, 0, null, null 29 | 30 | +SDL_GetAudioDeviceName c-string(index c-int, iscapture c-int) SDL2 extern 31 | 32 | +SDL_OpenAudioDevice SDL_AudioDeviceID( 33 | device c-string, 34 | iscapture c-int, 35 | desired SDL_AudioSpec*, 36 | obtained SDL_AudioSpec mut*, 37 | allowed_changes c-int, 38 | ) SDL2 extern 39 | 40 | +SDL_PauseAudioDevice void(dev SDL_AudioDeviceID, pause_on c-int) SDL2 extern 41 | 42 | +SDL_CloseAudioDevice void(dev SDL_AudioDeviceID) SDL2 extern 43 | -------------------------------------------------------------------------------- /demo/sound/convert-file.crow: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env crow 2 | import 3 | crow/io/path: get-extension 4 | crow/io/print: out, print 5 | audio/read-sound-file: read-sound-file 6 | audio/write-sound-file: flac, ogg-vorbis, sound-file-format, wav, write-sound-file 7 | audio/sound: format, show, with-sample-rate 8 | 9 | main nat(args string[]) summon, (native, sndfile) extern 10 | assert args.size == 2 : "Usage: crow convert-file.crow toccata.ogg toccata.flac" error 11 | in-path = args[0] 12 | out-path = args[1] 13 | ext = out-path get-extension ?? throw "Output file needs extension" error 14 | format sound-file-format = default-file-types[ext to] ?? throw describe-out-exts error 15 | 16 | sound = in-path.read-sound-file with-sample-rate 48000 17 | out print "sound format is {sound format}" 18 | out-path write-sound-file sound, format 19 | 0 20 | 21 | -describe-out-exts string() 22 | supported = ", " join for key, _ : default-file-types; key to 23 | "Supported output file extensions: {supported}" 24 | 25 | -default-file-types sound-file-format[symbol]() 26 | ("flac", flac), ("ogg", ogg-vorbis), ("wav", wav) 27 | -------------------------------------------------------------------------------- /include/crow/col/counter.crow: -------------------------------------------------------------------------------- 1 | no-std 2 | import 3 | ../bool: bool 4 | ../hash: hash-mix 5 | ../json: to 6 | ../misc: key 7 | ../number: ==, <=>, +, nat64 8 | ../option: ?? 9 | ../test-util: is 10 | ../tuple: new 11 | ./array: array, iterate 12 | ./collection: for-loop 13 | ./map: ~, iterate, map, subscript 14 | ./mut-map: mut-map, new, set-subscript, subscript, to 15 | 16 | +counter[k] record 17 | -inner nat64[k] 18 | 19 | +new[k] k counter(...a k[]) k key 20 | a to 21 | 22 | +to[k] k counter(values k[]) k key 23 | res nat64 mut[k] = () 24 | for x : values 25 | res[x] := (res[x] ?? 0) + 1 26 | res.to, 27 | 28 | +to[k] nat64[k](a k counter) k key 29 | a inner 30 | 31 | +subscript[k] nat64(a k counter, value k) k key 32 | a.inner[value] ?? 0 33 | 34 | +~[k] k counter(a k counter, value k) k key 35 | a.inner ~ (value, a[value] + 1), 36 | 37 | region spec impls (see collection.crow) 38 | 39 | +iterate[k] bool(a k counter, f bool mut(key k, count nat64)) k key 40 | a.inner iterate f 41 | 42 | test 43 | a nat64 counter = () 44 | a[1] is 0 45 | b = a ~ 3 46 | b[3] is 1 47 | c = b ~ 3 48 | c[3] is 2 49 | -------------------------------------------------------------------------------- /src/util/col/stackMap.d: -------------------------------------------------------------------------------- 1 | module util.col.stackMap; 2 | 3 | @safe @nogc pure nothrow: 4 | 5 | import util.util : ptrTrustMe; 6 | 7 | struct StackMap(K, V) { 8 | private: 9 | @disable this(ref const StackMap); 10 | immutable K key = invalid!K; 11 | V value = void; 12 | StackMap!(K, V)* next; 13 | } 14 | 15 | private immutable(K) invalid(K)() { 16 | static if (is(K == P*, P)) 17 | return null; 18 | else 19 | return K.INVALID; 20 | } 21 | 22 | ref inout(V) stackMapMustGet(K, V)(return ref inout(StackMap!(K, V)) a, scope immutable K key) { 23 | assert(a.key != invalid!K); 24 | return a.key == key 25 | ? a.value 26 | : stackMapMustGet!(K, V)(*a.next, key); 27 | } 28 | 29 | @trusted inout(StackMap!(K, V)) stackMapAdd(K, V)( 30 | return scope ref inout StackMap!(K, V) a, 31 | immutable K key, 32 | inout V value, 33 | ) { 34 | assert(key != invalid!K); 35 | return inout StackMap!(K, V)(key, value, cast(inout StackMap!(K, V)*) ptrTrustMe(a)); 36 | } 37 | 38 | @trusted T withStackMap(T, K, V)(in T delegate(ref StackMap!(K, V)) @safe @nogc pure nothrow cb) { 39 | StackMap!(K, V) map; 40 | return cb(map); 41 | } 42 | -------------------------------------------------------------------------------- /site-src/script/decode-tokens.crow: -------------------------------------------------------------------------------- 1 | import 2 | crow/js: cast, js-any 3 | ./lsp-types: new, token, tokens-legend, token-modifiers, token-types 4 | 5 | decode-tokens token[](a js-any, legend tokens-legend) unsafe, js extern 6 | encoded nat[] = for x : a.cast::js-any[]; x.cast::float.to 7 | with out : build 8 | prev-line mut nat = 0 9 | prev-character mut nat = 0 10 | i mut nat = 0 11 | next nat mut() = () => 12 | res = encoded[i] 13 | i +:= 1 14 | res 15 | while i < encoded.size 16 | line-delta = next[] 17 | character-delta = next[] 18 | line nat, character nat = if line-delta == 0 19 | prev-line, prev-character + character-delta 20 | else 21 | prev-line + line-delta, character-delta 22 | prev-line := line 23 | prev-character := character 24 | length = next[] 25 | type = legend.token-types[next[]] 26 | modifiers = next[] decode-modifiers legend.token-modifiers 27 | out ~= (line, character, length, type, modifiers) 28 | 29 | -decode-modifiers symbol[](encoded nat, legend symbol[]) 30 | assert legend.size == 1 31 | assert encoded == 0 || encoded == 1 32 | encoded == 0 ? () : legend 33 | -------------------------------------------------------------------------------- /test/end-to-end/compile-errors/fun-closure-errors.crow.out: -------------------------------------------------------------------------------- 1 | exit code: 0 2 | stderr: 3 | test/end-to-end/compile-errors/fun-closure-errors.crow 8:28-8:29 Can't access 'x' in a 'shared' lambda because it is a 'mut' local. 4 | test/end-to-end/compile-errors/fun-closure-errors.crow 11:32-11:33 Can't access 'y' in a 'data' lambda because it is of 'mut' type 'nat64 mut[]'. 5 | test/end-to-end/compile-errors/fun-closure-errors.crow 12:34-12:35 Can't access 'y' in a 'shared' lambda because it is of 'mut' type 'nat64 mut[]'. 6 | test/end-to-end/compile-errors/fun-closure-errors.crow 14:27-14:30 Can't call a 'summon' function from inside a 'data' lambda. 'sum void()' (from test/end-to-end/compile-errors/fun-closure-errors.crow line 28). 7 | test/end-to-end/compile-errors/fun-closure-errors.crow 16:30-16:33 Can't call a 'summon' function from inside a 'data' lambda. 'sum void()' (from test/end-to-end/compile-errors/fun-closure-errors.crow line 28). 8 | test/end-to-end/compile-errors/fun-closure-errors.crow 19:9-19:18 Can't call a 'summon' function from inside a 'data' lambda. 'sum void()' (from test/end-to-end/compile-errors/fun-closure-errors.crow line 28). 9 | -------------------------------------------------------------------------------- /demo/open-gl/texture.crow: -------------------------------------------------------------------------------- 1 | import 2 | OpenGL/gl 3 | OpenGL/headers 4 | ./load-bmp 5 | 6 | # Remember to call 'free-texture' 7 | load-texture-from-bmp GLuint(gl gl-ext, bmp-raw nat8[]) summon, unsafe, (native, SDL2) extern 8 | bmp-raw with-bmp image => 9 | texture mut GLuint = 0 10 | gl glGenTextures 1, &texture 11 | gl check-error "glGenTextures" 12 | 13 | gl glBindTexture GL_TEXTURE_2D, texture 14 | gl check-error "glBindTexture" 15 | w int32 = image.width to 16 | h int32 = image.height to 17 | image-data = image.image-data as-const 18 | gl glTexImage2D GL_TEXTURE_2D, 0, GL_RGBA, w, h, 0, GL_RGBA, GL_UNSIGNED_BYTE, image-data 19 | gl check-error "glTexImage2D" 20 | 21 | gl glTexParameteri GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR 22 | gl glTexParameteri GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR 23 | 24 | texture 25 | 26 | -check-error void(gl gl-ext, step string) summon, unsafe 27 | err GLenum = gl glGetError 28 | assert err == GL_NO_ERROR : "Loading image (in {step})" gl-error err 29 | 30 | free-texture void(gl gl-ext, tex-name GLuint) summon, unsafe, native extern 31 | gl glDeleteTextures 1, &tex-name 32 | -------------------------------------------------------------------------------- /demo/libraries/SDL2/SDL_render.crow: -------------------------------------------------------------------------------- 1 | import 2 | crow/c-types: c-int, u-int 3 | ./SDL_rect: SDL_Rect 4 | ./SDL_surface: SDL_Surface 5 | ./SDL_video: SDL_Window 6 | 7 | +SDL_Renderer extern 8 | +SDL_Texture extern 9 | 10 | +SDL_CreateRenderer SDL_Renderer mut*( 11 | window SDL_Window mut*, 12 | index c-int, 13 | render-flags SDL_RendererFlags, 14 | ) SDL2 extern 15 | 16 | +SDL_CreateTextureFromSurface SDL_Texture mut*( 17 | renderer SDL_Renderer mut*, 18 | surface SDL_Surface mut*, 19 | ) SDL2 extern 20 | 21 | +SDL_DestroyRenderer void(renderer SDL_Renderer mut*) SDL2 extern 22 | 23 | +SDL_DestroyTexture void(texture SDL_Texture mut*) SDL2 extern 24 | 25 | +SDL_RenderClear c-int(renderer SDL_Renderer mut*) SDL2 extern 26 | 27 | +SDL_RenderCopy c-int( 28 | renderer SDL_Renderer mut*, 29 | texture SDL_Texture mut*, 30 | src-rect SDL_Rect*, 31 | dest-rect SDL_Rect*, 32 | ) SDL2 extern 33 | 34 | +SDL_RendererFlags flags extern, u-int storage 35 | SDL_RENDERER_SOFTWARE = 1 36 | SDL_RENDERER_ACCELERATED = 2 37 | SDL_RENDERER_PRESENTVSYNC = 4 38 | SDL_RENDERER_TARGETTEXTURE = 8 39 | 40 | +SDL_RenderPresent void(renderer SDL_Renderer mut*) SDL2 extern 41 | -------------------------------------------------------------------------------- /demo/webapp/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Demo App 6 | 7 | 8 | 9 |
10 | 11 |

Register

12 |
13 | : 14 | : 15 | 16 |
17 | 18 |

Login

19 |
20 | : 21 | : 22 | 23 |
24 | 25 |

Post

26 |
27 | 28 | 29 |
30 | 31 |

Users

32 |
33 |
34 | 35 |

Posts

36 |
37 |
38 | 39 | 40 | -------------------------------------------------------------------------------- /test/unit/library/col/frozen-map-tests.crow: -------------------------------------------------------------------------------- 1 | import 2 | ../../../../include/crow/col/experimental/frozen-map 3 | 4 | dummy-frozen-map-tests nat64() 5 | 0 6 | 7 | -verify void(a (nat64, string) frozen-map, keys-order nat64[], bucket-starts nat64[]) 8 | (for k, _ : a pairs; k)::nat64[] is keys-order 9 | a.bucket-starts is bucket-starts 10 | 11 | test 12 | a (nat64, string) frozen-map = () 13 | a.is-empty is true 14 | a.size is 0 15 | a verify (), () 16 | a[0] is () 17 | 18 | b (nat64, string) frozen-map = (3, "3"), (1, "1"), (5, "5"), (2, "2") 19 | b verify (3, 1, 5, 2), () 20 | b[0] is () 21 | b[1] is ("1",) 22 | b[2] is ("2",) 23 | b[3] is ("3",) 24 | b[4] is () 25 | b[5] is ("5",) 26 | b[6] is () 27 | 28 | c (nat64, string) frozen-map = (3, "3"), (1, "1"), (5, "5"), (2, "2"), (8, "8") 29 | c verify (2, 8, 3, 5, 1), (0, 2) 30 | c[0] is () 31 | c[1] is ("1",) 32 | c[2] is ("2",) 33 | c[3] is ("3",) 34 | c[4] is () 35 | c[5] is ("5",) 36 | c[6] is () 37 | c[7] is () 38 | c[8] is ("8",) 39 | c[9] is () 40 | 41 | test 42 | a (nat64, string) frozen-map = (1, "1"), (1, "2") 43 | a.size is 1 44 | a verify (1,), () 45 | a[1] is ("2",) 46 | -------------------------------------------------------------------------------- /src/frontend/check/maps.d: -------------------------------------------------------------------------------- 1 | module frontend.check.maps; 2 | 3 | @safe @nogc pure nothrow: 4 | 5 | import model.ast : ImportOrExportAst; 6 | import model.model : FunDecl, SpecDecl, StructOrAlias, Test; 7 | import util.col.array : allSame, SmallArray; 8 | import util.col.hashTable : HashTable; 9 | import util.symbol : Symbol; 10 | import util.unicode : FileContent; 11 | 12 | alias StructsAndAliasesMap = HashTable!(StructOrAlias, Symbol, structOrAliasName); 13 | alias SpecsMap = HashTable!(immutable SpecDecl*, Symbol, specDeclName); 14 | alias FunsMap = HashTable!(immutable FunDecl*[], Symbol, funDeclsName); 15 | 16 | immutable struct FunsAndMap { 17 | SmallArray!FunDecl funs; 18 | SmallArray!Test tests; 19 | FunsMap funsMap; 20 | } 21 | 22 | immutable struct ImportOrExportFile { 23 | ImportOrExportAst* source; 24 | FileContent* content; 25 | } 26 | 27 | Symbol structOrAliasName(in StructOrAlias a) => 28 | a.name; 29 | 30 | Symbol funDeclsName(in immutable FunDecl*[] a) { 31 | assert(allSame!(Symbol, immutable FunDecl*)(a, (in immutable FunDecl* x) => 32 | x.name)); 33 | return a[0].name; 34 | } 35 | 36 | Symbol specDeclName(in SpecDecl* a) => 37 | a.name; 38 | -------------------------------------------------------------------------------- /test/end-to-end/compile-errors/record-privacy-a.crow.out: -------------------------------------------------------------------------------- 1 | exit code: 0 2 | stderr: 3 | test/end-to-end/compile-errors/record-privacy-a.crow 7:26-7:27 The 'new' function for 'redundant-private' is already private by default (derived from visibility of fields). 4 | test/end-to-end/compile-errors/record-privacy-a.crow 13:27-13:28 The 'new' function for 'redundant-internal' is already internal by default (derived from visibility of fields). 5 | test/end-to-end/compile-errors/record-privacy-a.crow 14:5-14:6 Fields of record 'redundant-internal' are already internal by default. 6 | test/end-to-end/compile-errors/record-privacy-a.crow 16:26-16:27 The 'new' function for 'redundant-public' is already public by default (derived from visibility of fields). 7 | test/end-to-end/compile-errors/record-privacy-a.crow 17:5-17:6 Fields of record 'redundant-public' are already public by default. 8 | test/end-to-end/compile-errors/record-privacy-a.crow 19:25-19:26 'new' function for record 'private-mut' should not have greater visibility than private (derived from visibility of fields). 9 | test/end-to-end/compile-errors/record-privacy-a.crow 22:8-22:9 Field 'l' mutability would already be private by default. 10 | -------------------------------------------------------------------------------- /include/system/time.crow: -------------------------------------------------------------------------------- 1 | no-std 2 | import 3 | crow/c-types: err-t, size_t, long 4 | crow/pointer: const-pointer, mut-pointer 5 | crow/private/c-string-util: char8, c-string 6 | 7 | +timespec record(tv_sec long, tv_nsec long) extern 8 | 9 | +new timespec() bare 10 | 0, 0 11 | 12 | +tm extern 13 | 14 | +nanosleep err-t(requested_time timespec*, remaining timespec mut*) posix extern 15 | 16 | # TODO: should not be 'pure' 17 | +clock_gettime err-t(clock-id __clockid_t, timespec timespec mut*) posix extern, pure 18 | 19 | +gmtime tm mut*(timer time_t*) posix extern 20 | 21 | +localtime tm mut*(timer time_t*) posix extern 22 | 23 | +time time_t(timer time_t mut*) posix extern 24 | 25 | +strftime size_t(s char8 mut*, max-size size_t, format c-string, tp tm*) posix extern 26 | 27 | +__clockid_t enum extern 28 | CLOCK_REALTIME = 0 29 | CLOCK_MONOTONIC = 1 30 | CLOCK_PROCESS_CPUTIME_ID = 2 31 | CLOCK_THREAD_CPUTIME_ID = 3 32 | CLOCK_MONOTONIC_RAW = 4 33 | CLOCK_REALTIME_COARSE = 5 34 | CLOCK_MONOTONIC_COARSE = 6 35 | CLOCK_BOOTTIME = 7 36 | CLOCK_REALTIME_ALARM = 8 37 | CLOCK_BOOTTIME_ALARM = 9 38 | CLOCK_TAI = 11 39 | 40 | # Seconds since the Epoch 41 | +time_t alias 42 | long 43 | -------------------------------------------------------------------------------- /include/crow/c-types.crow: -------------------------------------------------------------------------------- 1 | ### 2 | Types for compatibility with C. 3 | ### 4 | 5 | no-std 6 | import 7 | ./private/bootstrap: char8, float32, int16, int32, int64, nat16, nat32, nat64 8 | 9 | +c-char alias 10 | char8 11 | 12 | # Equivalent to C's `float` type. 13 | +c-float alias 14 | float32 15 | 16 | +short alias 17 | int16 18 | 19 | # Equivalent to C's `int` type. 20 | +c-int alias 21 | int32 22 | 23 | # Equivalent to C's `size_t` type. 24 | +size_t alias 25 | nat64 26 | 27 | # Equivalent to C's `ssize_t` type. 28 | +ssize_t alias 29 | int64 30 | 31 | +u-short alias 32 | nat16 33 | 34 | # Equivalent to C's `unsigned int` type. 35 | +u-int alias 36 | nat32 37 | 38 | # Equivalent to C's `unsigned long` type. 39 | +u-long alias 40 | nat64 41 | 42 | # Equivalent to C's `unsigned long long` type. 43 | +u-long-long alias 44 | nat64 45 | 46 | # Equivalent to C's `long` type. 47 | +long alias 48 | int64 49 | 50 | # Equivalent to C's `long long` type. 51 | +long-long alias 52 | int64 53 | 54 | ### 55 | Error code typically returned by POSIX functions. 56 | ### 57 | +err-t alias 58 | int32 59 | 60 | # File descriptor type typically used by POSIX functions. 61 | +fd-t alias 62 | int32 63 | -------------------------------------------------------------------------------- /include/system/unistd.crow: -------------------------------------------------------------------------------- 1 | no-std 2 | import 3 | crow/c-types: c-int, err-t, fd-t, size_t 4 | crow/pointer: any-const-pointer, any-mut-pointer, const-pointer, mut-pointer 5 | crow/private/c-string-util: char8, c-string 6 | crow/private/number-low-level: int32, int64, nat32 7 | ./sys/types: off_t 8 | 9 | +getcwd char8 mut*(buf char8 mut*, size size_t) posix extern 10 | 11 | +readlink ssize_t(path c-string, buf char8 mut*, len size_t) posix extern 12 | +symlink c-int(target c-string, linkpath c-string) posix extern 13 | 14 | +close err-t(fd fd-t) libc extern 15 | +lseek off_t(f fd-t, offset off_t, whence int32) posix extern 16 | +read ssize_t(fd fd-t, buff any-mut-pointer, n-bytes size_t) posix extern 17 | +write ssize_t(fd fd-t, buf any-const-pointer, n-bytes size_t) posix extern 18 | 19 | +pipe err-t(pipes pipes mut*) posix extern 20 | 21 | # The headers just use int[2], but this is easier to use from crow 22 | +pipes record(write-pipe fd-t, read-pipe fd-t) extern, mut 23 | 24 | +__environ global(c-string*) posix extern 25 | 26 | +usleep c-int(micro-seconds nat32) posix extern 27 | 28 | +ssize_t alias 29 | int64 30 | 31 | +rmdir err-t(path c-string) libc extern 32 | 33 | +unlink err-t(path c-string) posix extern 34 | -------------------------------------------------------------------------------- /test/end-to-end/compile-errors/auto-fun-errors.crow.out: -------------------------------------------------------------------------------- 1 | exit code: 0 2 | stderr: 3 | test/end-to-end/compile-errors/auto-fun-errors.crow 9:1-9:3 Automatic 'to json' can't be 'bare'. 4 | test/end-to-end/compile-errors/auto-fun-errors.crow 11:1-11:5 Function needs a body. (An automatic function must be named '==', '<=>', or 'to'.) 5 | test/end-to-end/compile-errors/auto-fun-errors.crow 13:1-13:3 '==' must take two parameters of the same type. 6 | test/end-to-end/compile-errors/auto-fun-errors.crow 15:1-15:3 'to' must take a single parameter. 7 | test/end-to-end/compile-errors/auto-fun-errors.crow 17:1-17:3 An automatic function parameter must be a 'record' or 'union' type. 8 | test/end-to-end/compile-errors/auto-fun-errors.crow 20:1-20:3 An automatic function parameter must be a 'record' or 'union' type. 9 | test/end-to-end/compile-errors/auto-fun-errors.crow 23:1-23:3 '==' must return 'bool'. 10 | test/end-to-end/compile-errors/auto-fun-errors.crow 24:1-24:4 '<=>' must return 'comparison'. 11 | test/end-to-end/compile-errors/auto-fun-errors.crow 25:1-25:3 'to' must return 'json'. 12 | test/end-to-end/compile-errors/auto-fun-errors.crow 27:1-27:3 This function can't be automatic because the type is not fully visible in this context. 13 | -------------------------------------------------------------------------------- /test/unit/parallel.crow: -------------------------------------------------------------------------------- 1 | import 2 | ../../include/crow/private/future-low-level: 3 | as-future, as-future-impl, future-impl, is-completed, resolve, unresolved 4 | 5 | dummy-parallel nat() 6 | 0 7 | 8 | test 9 | out nat mut[] = () 10 | f void future = with : later 11 | out ~= 2 12 | out ~= 1 13 | f await 14 | out.to::nat[] is (1, 2) 15 | 16 | # Test future awaited by multiple fibers at once 17 | test 18 | f nat future = with : later 19 | 1 20 | a0 nat future = with : parallel 21 | f.await + 1 22 | a1 nat future = with : parallel 23 | f.await + 2 24 | a0.await is 2 25 | a1.await is 3 26 | 27 | # This tests 'shared-of-mut-lambda', which the compiler uses to implement 'shared' lambdas. 28 | test 29 | out nat mut[] = () 30 | f void shared(x nat) = shared x => 31 | out ~= x 32 | () 33 | for x : 0::nat .. 10 parallel 34 | f[x] 35 | out.move-to.sort::nat[] is for x : 0::nat .. 10; x 36 | () 37 | 38 | test trusted, native extern 39 | a nat future-impl = unresolved 40 | b nat future-impl = unresolved 41 | both (nat, nat) future = with : parallel 42 | a.as-future.await, b.as-future.await 43 | a resolve 1 44 | forbid both.as-future-impl is-completed 45 | b resolve 2 46 | both.await is (1, 2) 47 | () 48 | -------------------------------------------------------------------------------- /include/crow/io/private/time-low-level.crow: -------------------------------------------------------------------------------- 1 | no-std 2 | import 3 | crow/js: call-property, cast, js-global 4 | system/time: clock_gettime, CLOCK_MONOTONIC, new, timespec, tv_nsec, tv_sec 5 | system/win32: GetTickCount 6 | ../../number: ==, +, *, /, %, float, int64, to 7 | ../../private/bootstrap: nat64, todo 8 | 9 | # Monotime in nanoseconds. 10 | timestamp alias 11 | nat64 12 | 13 | ### 14 | Get the value from a monotonic clock. 15 | TODO: This should be 'summon', but I didn't mark it that way so 'perf' can use it. 16 | ### 17 | get-monotime-nsec timestamp() bare, trusted, native extern 18 | if extern windows 19 | GetTickCount.to msec-to-nsec 20 | elif extern posix 21 | time mut timespec = () 22 | err = CLOCK_MONOTONIC clock_gettime &time 23 | assert err == 0 : todo 24 | time.tv_sec.to * 1000000000 + time.tv_nsec.to 25 | elif extern js 26 | msec float = "performance".js-global call-property "now" cast 27 | msec * 1_000_000 to 28 | else 29 | todo 30 | 31 | -msec-to-nsec nat64(a nat64) bare 32 | a * 1_000_000 33 | 34 | nsec-to-msec nat64(a nat64) bare 35 | a / 1_000_000 36 | 37 | to-timespec timespec(a timestamp) bare, unsafe 38 | second nat64 = 1000000000 39 | seconds int64 = a / second to 40 | ns int64 = a % second to 41 | seconds, ns 42 | -------------------------------------------------------------------------------- /include/crow/private/range-low-level.crow: -------------------------------------------------------------------------------- 1 | no-std 2 | import 3 | ../bool: bool, false, true 4 | ../compare: <=, >=, compare 5 | ../fun-util: subscript 6 | ./number-low-level: nat64 7 | 8 | ### 9 | Range of values. `low` is inclusive and `high` is exclusive. 10 | 11 | Usable for any type with a comparison function. 12 | ### 13 | +range[t] record(low t, high t) by-val 14 | 15 | +forward-rangeable[t] spec t compare 16 | + t(a t, distance nat64) 17 | 18 | +subtract-to-nat[t] spec 19 | - nat64(a t, b t) 20 | 21 | # Spec for types that support most range operations 22 | +rangeable[t] spec t forward-rangeable, t subtract-to-nat 23 | - t(a t, distance nat64) 24 | 25 | # Create a range from `low` (inclusive) to `high` (exclusive). 26 | +..[t] t range(low t, high t) bare, t compare 27 | assert low <= high 28 | low, high 29 | 30 | # Size of the range; depends on a `-` function existing. 31 | +size[t] nat64(a t range) bare, t subtract-to-nat 32 | a.high - a.low 33 | 34 | # Calls `f` for each value in the range, from `a.low` to `a.high - 1`. 35 | +iterate[t] bool(a t range, f bool mut(elem t)) t forward-rangeable 36 | cur mut = a low 37 | loop 38 | if cur >= a.high 39 | break false 40 | elif f[cur] 41 | break true 42 | else 43 | cur +:= 1 44 | continue 45 | -------------------------------------------------------------------------------- /include/crow/private/c-string-util.crow: -------------------------------------------------------------------------------- 1 | no-std 2 | import 3 | ../bool: bool 4 | ../number: +, nat8, nat64 5 | ../option: new, option 6 | ../pointer: +, -, *, as-const, as-mut, mut-pointer 7 | export 8 | ./bootstrap: char8, c-string 9 | 10 | +to char8(a nat8) builtin, bare 11 | +to nat8(a char8) builtin, bare 12 | +== bool(a char8, b char8) bare, builtin 13 | 14 | ### 15 | Walk a c-string and return a pointer to the first occurrence of `c`. 16 | If that is not found, return an empty option. 17 | ### 18 | find-char-in-c-string c-string?(a c-string, c char8) bare, unsafe, native extern 19 | cur mut = a 20 | loop 21 | if *cur == c 22 | break cur, 23 | elif *cur == "\0" 24 | break 25 | else 26 | cur +:= 1 27 | continue 28 | 29 | # Pointer to the end of a c-string. 30 | find-c-string-end c-string(a c-string) bare, unsafe, native extern 31 | cur mut = a 32 | until *cur == "\0" 33 | cur +:= 1 34 | cur 35 | 36 | # Pointer to the end of a c-string. 37 | find-c-string-end char8 mut*(a char8 mut*) bare, unsafe, native extern 38 | a.as-const.find-c-string-end as-mut 39 | 40 | c-string-size nat64(a c-string) bare, unsafe, native extern 41 | a.find-c-string-end - a 42 | 43 | c-string-size-incl-nul nat64(a c-string) bare, unsafe, native extern 44 | a.c-string-size + 1 45 | -------------------------------------------------------------------------------- /include/system/spawn.crow: -------------------------------------------------------------------------------- 1 | no-std 2 | import 3 | crow/c-types: err-t, fd-t 4 | crow/number: int32 5 | crow/pointer: any-const-pointer, const-pointer, mut-pointer 6 | crow/string: c-string 7 | system/sys/types: mode_t, pid_t 8 | 9 | +posix_spawn_file_actions_t extern(80) 10 | 11 | # TODO: type file-actions and attrp, currently these are always null 12 | # /usr/include/spawn.h 13 | +posix_spawn err-t( 14 | pid pid_t mut*, 15 | executable-path c-string, 16 | file-actions posix_spawn_file_actions_t*, 17 | attrp any-const-pointer, 18 | argv c-string*, 19 | environ c-string*, 20 | ) posix extern 21 | 22 | +posix_spawn_file_actions_init err-t(file-actions posix_spawn_file_actions_t mut*) posix extern 23 | +posix_spawn_file_actions_destroy err-t( 24 | file-actions posix_spawn_file_actions_t mut*, 25 | ) posix extern 26 | +posix_spawn_file_actions_addopen err-t( 27 | file-actions posix_spawn_file_actions_t mut*, 28 | fd fd-t, 29 | path c-string, 30 | oflag int32, 31 | mode mode_t, 32 | ) posix extern 33 | +posix_spawn_file_actions_addclose err-t( 34 | file-actions posix_spawn_file_actions_t mut*, 35 | fd fd-t, 36 | ) posix extern 37 | +posix_spawn_file_actions_adddup2 err-t( 38 | file-actions posix_spawn_file_actions_t mut*, 39 | fd fd-t, 40 | new-fd fd-t, 41 | ) posix extern 42 | -------------------------------------------------------------------------------- /test/end-to-end/compile-errors/data-spec-with-type-args.crow: -------------------------------------------------------------------------------- 1 | main void() 2 | # type is data 3 | d d = 0, 4 | d takes-data 5 | 6 | # type is mut 7 | m m = 0, 8 | m takes-data 9 | 10 | # type is data and type arg is data 11 | dd d dt = (0,), 12 | dd takes-dt 13 | dd takes-dt-t-data 14 | dd takes-data 15 | 16 | # type is mut and type arg is mut 17 | mm m mt = (0,), 18 | mm takes-mt 19 | mm takes-mt-t-data 20 | mm takes-data 21 | 22 | # type is mutable but type arg is data 23 | dm d mt = (0,), 24 | dm takes-mt 25 | dm takes-mt-t-data 26 | dm takes-data 27 | 28 | # type is data but type arg is mut 29 | md m dt = (0,), 30 | md takes-dt 31 | md takes-dt-t-data 32 | md takes-data 33 | 34 | d indirect 35 | m indirect 36 | 37 | d record 38 | value nat64 39 | m record mut 40 | value mut nat64 41 | dt[t] record 42 | inner t 43 | mt[t] record mut 44 | value t 45 | 46 | takes-dt[t] void(a t dt) 47 | a takes-dt-t-data 48 | 49 | takes-mt[t] void(a t mt) 50 | a takes-mt-t-data 51 | 52 | takes-dt-t-data[t] void(a t dt) t data 53 | a takes-data 54 | 55 | takes-mt-t-data[t] void(a t mt) t data 56 | a takes-data 57 | 58 | takes-data[t] void(_ t) t data 59 | () 60 | 61 | takes-data[t] spec 62 | takes-data void(_ t) 63 | indirect[t] void(_ t) t takes-data 64 | () 65 | -------------------------------------------------------------------------------- /demo/sound/main.crow: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env crow 2 | import 3 | crow/io/duration: second 4 | crow/io/print: out, print 5 | crow/io/time: delay 6 | audio/audio: clear, format, pause, play, play-loop, restart, resume, shut-down 7 | audio/sdl-audio: start-sdl-audio 8 | audio/read-sound-file: sound-from-file-content 9 | audio/sound: *, sample-rate, show, with-sample-rate 10 | ./toccata.ogg as toccata nat8 array 11 | ./crow.wav as crow-wav nat8 array 12 | 13 | main void() summon, (native, SDL2, sndfile) extern 14 | audio = start-sdl-audio 15 | out print "Sound device format is {audio format}" 16 | music = toccata.sound-from-file-content with-sample-rate audio.format.sample-rate 17 | crow-sound = crow-wav.sound-from-file-content with-sample-rate audio.format.sample-rate 18 | 19 | 1.second delay 20 | out print "start music" 21 | playing = audio play-loop music 22 | 23 | 3.second delay 24 | out print "pause" 25 | playing pause 26 | 27 | 3.second delay 28 | out print "crow!" 29 | cr = audio play crow-sound * 0.1 30 | 31 | 3.second delay 32 | out print "resume" 33 | playing resume 34 | 35 | 3.second delay 36 | out print "crow!" 37 | cr restart 38 | 39 | 3.second delay 40 | out print "clear" 41 | audio clear 42 | 43 | 3.second delay 44 | out print "shut down" 45 | audio shut-down 46 | -------------------------------------------------------------------------------- /include/system/sys/stat.crow: -------------------------------------------------------------------------------- 1 | no-std 2 | import 3 | crow/c-types: c-int, err-t, u-long, u-long-long 4 | crow/number: nat32 5 | crow/pointer: mut-pointer 6 | crow/string: c-string 7 | system/sys/types: 8 | blkcnt_t, blksize_t, dev_t, gid_t, ino_t, mode_t, nlink_t, off_t, time_t, uid_t 9 | 10 | +stat record extern 11 | st_dev dev_t 12 | pad0 nat32 13 | st_ino_unused ino_t 14 | st_mode mode_t 15 | st_nlink nlink_t 16 | st_uid uid_t 17 | st_gid gid_t 18 | st_rdev dev_t 19 | pad1 nat32 20 | sts_ize off_t 21 | st_blksize blksize_t 22 | st_blocks blkcnt_t 23 | st_atime time_t 24 | st_atime_nsec u-long 25 | st_mtime time_t 26 | st_mtime_nsec u-long 27 | st_ctime time_t 28 | st_ctime_nsec u-long 29 | st_ino u-long-long 30 | -unused u-long-long 31 | 32 | +new stat() 33 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 34 | 35 | -__xstat c-int(ver c-int, path c-string, buf stat mut*) posix extern 36 | +stat c-int(path c-string, buf stat mut*) summon, unsafe, posix extern 37 | 0 __xstat path, buf 38 | 39 | +S_IFMT nat32() bare 40 | # TODO: "octal170000" 41 | 61440 42 | 43 | +S_IFDIR nat32() bare 44 | # TODO: "octal40000" 45 | 16384 46 | 47 | +S_IFREG nat32() bare 48 | # TODO: "octal100000" 49 | 32768 50 | 51 | +mkdir err-t(path c-string, mode mode_t) posix extern 52 | -------------------------------------------------------------------------------- /test/end-to-end/compile-errors/call-should-use-syntax.crow.out: -------------------------------------------------------------------------------- 1 | exit code: 0 2 | stderr: 3 | test/end-to-end/compile-errors/call-should-use-syntax.crow 3:17-3:26 Prefer to write a 'for' loop instead of calling 'for-break'. 4 | test/end-to-end/compile-errors/call-should-use-syntax.crow 4:25-4:30 Prefer to write 'x!' instead of 'x.force'. 5 | test/end-to-end/compile-errors/call-should-use-syntax.crow 5:21-5:29 Prefer to write a 'for' loop instead of calling 'for-loop'. 6 | test/end-to-end/compile-errors/call-should-use-syntax.crow 6:18-6:21 Prefer to write '()' instead of 'new'. 7 | test/end-to-end/compile-errors/call-should-use-syntax.crow 7:26-7:29 Prefer to write '(x,)' instead of 'x.new'. 8 | test/end-to-end/compile-errors/call-should-use-syntax.crow 8:26-8:29 Prefer to write 'x, y' instead of 'x new y'. 9 | test/end-to-end/compile-errors/call-should-use-syntax.crow 9:21-9:24 Prefer to write '!x' instead of 'x.not' 10 | test/end-to-end/compile-errors/call-should-use-syntax.crow 10:8-10:21 Prefer to write 'x[i] := y' instead of 'x set-subscript i, y'. 11 | test/end-to-end/compile-errors/call-should-use-syntax.crow 11:12-11:21 Prefer to write 'x[i]' instead of 'x subscript i'. 12 | test/end-to-end/compile-errors/call-should-use-syntax.crow 12:30-12:40 Prefer to write a 'with' block instead of calling 'with-block'. 13 | -------------------------------------------------------------------------------- /include/crow/crypto/experimental/login-cookie.crow: -------------------------------------------------------------------------------- 1 | import 2 | ../../io/time: get-unix-time, new, seconds-since-epoch, unix-time 3 | ../../parse: ~~, grammar, int, map, nat 4 | ../../serialize: from-bytes, to-8-bytes 5 | ../random: random 6 | 7 | +login-cookie record(timestamp unix-time, cookie nat64) 8 | 9 | +cookie-matches bool(a login-cookie, cookie nat64, expire-seconds nat64) summon, native extern 10 | now = get-unix-time seconds-since-epoch 11 | recent = now - a.timestamp.seconds-since-epoch < expire-seconds.to 12 | unless recent 13 | then = a.timestamp seconds-since-epoch 14 | info log "Cookie expired! now: {now}, then: {then}, expire after: {expire-seconds}" 15 | unless a.cookie == cookie 16 | info log "Wrong cookie! expected: {a cookie}, got: {cookie}" 17 | recent && a.cookie == cookie 18 | 19 | +generate-login-cookie login-cookie() summon, native extern 20 | get-unix-time, random 21 | 22 | +to-bytes nat8[](a login-cookie) 23 | a.timestamp.seconds-since-epoch.to-8-bytes ~~ a.cookie.to-8-bytes 24 | 25 | +from-bytes login-cookie(a nat8[]) 26 | assert a.size == 16 27 | (a[0 .. 8].from-bytes,), a[8 .. 16].from-bytes 28 | 29 | +show string(a login-cookie) 30 | "{a.timestamp seconds-since-epoch}|{a cookie}" 31 | 32 | +login-cookie login-cookie grammar() 33 | int ~~ "|" ~~ nat map (time, cookie) => 34 | (time,), cookie 35 | -------------------------------------------------------------------------------- /include/crow/option.crow: -------------------------------------------------------------------------------- 1 | no-std 2 | import 3 | ./bool: bool, new, true 4 | ./compare: compare, comparison, equal 5 | ./misc: ==, <=> 6 | ./number: nat64, new 7 | ./private/bootstrap: exception, none, some, string 8 | export 9 | ./private/bootstrap: option 10 | 11 | # Empty option. 12 | +new[t] t?() bare 13 | none 14 | 15 | # Option containing `a`. 16 | +new[t] t?(a t) bare 17 | a some 18 | 19 | +==[t] bool(a t?, b t?) bare, t equal 20 | +<=>[t] comparison(a t?, b t?) bare, t compare 21 | 22 | # True iff `a` is an empty option. 23 | +is-empty[t] bool(a t?) bare 24 | unless _ ?= a 25 | true 26 | 27 | # 1 if `a` has a value, else 0. 28 | +size[t] nat64(a t?) bare 29 | unless a is-empty 30 | 1 31 | 32 | ### 33 | Lazily-evaluated. 34 | If `a` is non-empty, returns it and does not evaluate `b`. 35 | Else, returns `b`. 36 | ### 37 | +||[t] t?(a t?, b t?) builtin, bare 38 | 39 | ### 40 | Lazily-evaluated. 41 | If `a` is non-empty, returns its value and does not evaluate `b`. 42 | Else, returns `b`. 43 | ### 44 | +??[t] t(a t?, default t) builtin, bare 45 | 46 | ### 47 | Called like 'a!' 48 | If `a` is non-empty, returns its value; else throws. 49 | ### 50 | +force[t] t(a t?) bare 51 | a ?? throw force-option-error 52 | +force-option-error record exception variant-member 53 | +show string(_ force-option-error) 54 | "Tried to force empty option" 55 | 56 | -------------------------------------------------------------------------------- /include/system/stdio.crow: -------------------------------------------------------------------------------- 1 | no-std 2 | import 3 | crow/bool: bool 4 | crow/c-types: c-int, err-t, fd-t, size_t, long 5 | crow/misc: void 6 | crow/number: nat8, nat32 7 | crow/pointer: const-pointer, mut-pointer 8 | crow/private/c-string-util: char8, c-string 9 | 10 | +perror void(s c-string) libc extern 11 | 12 | +stdin fd-t() bare 13 | 0 14 | +stdout fd-t() bare 15 | 1 16 | +stderr fd-t() bare 17 | 2 18 | 19 | +puts err-t(s c-string) libc extern 20 | 21 | +FILE extern 22 | 23 | +popen FILE mut*(command c-string, modes c-string) libc extern 24 | +pclose c-int(stream FILE mut*) libc extern 25 | 26 | +feof bool(stream FILE mut*) libc extern 27 | +fgets char8 mut*(s char8 mut*, n c-int, stream FILE mut*) libc extern 28 | 29 | +fopen FILE mut*(filename c-string, mode c-string) libc extern 30 | +fclose c-int(stream FILE mut*) libc extern 31 | +fseek c-int(stream FILE mut*, offset long, whence SEEK) libc extern 32 | +ftell long(stream FILE mut*) libc extern 33 | +ferror bool(stream FILE mut*) libc extern 34 | +fread size_t( 35 | _Buffer nat8 mut*, 36 | _ElementSize size_t, 37 | _ElementCount size_t, 38 | _Stream FILE mut*, 39 | ) libc extern 40 | +fwrite size_t( 41 | _Buffer nat8*, 42 | _ElementSize size_t, 43 | _ElementCount size_t, 44 | _Stream FILE mut*, 45 | ) libc extern 46 | 47 | +SEEK enum(SEEK_SET, SEEK_CUR, SEEK_END) extern, nat32 storage 48 | -------------------------------------------------------------------------------- /src/util/late.d: -------------------------------------------------------------------------------- 1 | module util.late; 2 | 3 | @safe @nogc pure nothrow: 4 | 5 | import util.memory : initMemory; 6 | import util.opt : force, has, MutOpt, Opt, none, some, someMut; 7 | 8 | struct MutLate(T) { 9 | private MutOpt!T value_; 10 | } 11 | 12 | inout(T) lateGet(T)(ref inout MutLate!T a) => 13 | force(a.value_); 14 | 15 | void lateSet(T)(ref MutLate!T a, T value) { 16 | assert(!has(a.value_)); 17 | a.value_ = someMut(value); 18 | } 19 | 20 | immutable struct Late(T) { 21 | private Opt!T value_; 22 | } 23 | 24 | @trusted Late!T late(T)() => 25 | Late!T(none!T); 26 | 27 | @trusted Late!T late(T)(T value) => 28 | Late!T(some(value)); 29 | 30 | bool lateIsSet(T)(ref Late!T a) => 31 | has(a.value_); 32 | 33 | @trusted ref immutable(T) lateGet(T)(return scope ref Late!T a) { 34 | assert(lateIsSet(a)); 35 | return force(a.value_); 36 | } 37 | 38 | @trusted void lateSet(T)(ref Late!T a, T value) { 39 | assert(!lateIsSet(a)); 40 | initMemory(&a.value_, some(value)); 41 | } 42 | 43 | // TODO: we shouldn't do this 44 | @trusted void lateSetOverwrite(T)(ref Late!T a, T value) { 45 | assert(lateIsSet(a)); 46 | initMemory(&a.value_, some(value)); 47 | } 48 | 49 | ref immutable(T) lazilySet(T)(ref Late!T a, in immutable(T) delegate() @safe @nogc pure nothrow cb) { 50 | if (!lateIsSet(a)) 51 | lateSet!T(a, cb()); 52 | return lateGet!T(a); 53 | } 54 | -------------------------------------------------------------------------------- /demo/libraries/audio/write-sound-file.crow: -------------------------------------------------------------------------------- 1 | import 2 | crow/io/print: out, print 3 | sndfile/headers 4 | sndfile/util: check-sndfile-error 5 | ./sound: format, n-channels, sample-rate, samples, sound 6 | 7 | +sound-file-format enum(flac, ogg-vorbis, wav) 8 | 9 | +write-sound-file void( 10 | path string, 11 | sound sound, 12 | format sound-file-format, 13 | ) summon, (native, sndfile) extern 14 | n-channels = sound.format n-channels 15 | n-frames = sound.samples.size / n-channels 16 | sf-format = format to-sf-format 17 | out print "sf-format is {sf-format.to::string}" 18 | trusted 19 | info mut SF_INFO = n-frames, sound.format.sample-rate.to, n-channels.to, sf-format, 1, 1 20 | f = path.to sf_open SFM_WRITE, &info 21 | out print "f.sf_error is {f sf_error}" 22 | f.sf_error check-sndfile-error 23 | out print "write {sound.samples.size} samples" 24 | n-written = f sf_write_float sound.samples.begin-pointer, sound.samples.size 25 | f.sf_close check-sndfile-error 26 | out print "n-written is {n-written}; samples size is {sound.samples.size}" 27 | assert n-written == sound.samples.size 28 | 29 | -to-sf-format SF_FORMAT(a sound-file-format) summon 30 | match a 31 | as flac 32 | SF_FORMAT_FLAC | SF_FORMAT_PCM_16 33 | as ogg-vorbis 34 | SF_FORMAT_OGG | SF_FORMAT_VORBIS | SF_FORMAT_PCM_32 35 | as wav 36 | SF_FORMAT_WAV | SF_FORMAT_PCM_16 37 | -------------------------------------------------------------------------------- /include/crow/private/libunwind.crow: -------------------------------------------------------------------------------- 1 | no-std 2 | import 3 | ../c-types: c-char, c-int, size_t 4 | ../number: nat64 5 | ../pointer: mut-pointer 6 | 7 | unw_word_t alias 8 | nat64 9 | unw_cursor_t extern(1024) 10 | unw_context_t extern(1024) 11 | 12 | # TODO: aliases for different machine types 13 | unw_getcontext c-int(context unw_context_t mut*) bare, unsafe, unwind extern 14 | context _Ux86_64_getcontext 15 | unw_init_local c-int( 16 | cursor unw_cursor_t mut*, 17 | context unw_context_t mut*, 18 | ) bare, unsafe, unwind extern 19 | cursor _ULx86_64_init_local context 20 | unw_step c-int(cursor unw_cursor_t mut*) bare, unsafe, unwind extern 21 | cursor _ULx86_64_step 22 | unw_get_proc_name c-int( 23 | cursor unw_cursor_t mut*, 24 | begin c-char mut*, 25 | size size_t, 26 | offset unw_word_t mut*, 27 | ) bare, unsafe, unwind extern 28 | cursor _ULx86_64_get_proc_name begin, size, offset 29 | 30 | # TODO: These should not be 'pure' 31 | -_Ux86_64_getcontext c-int(context unw_context_t mut*) unwind extern, pure 32 | -_ULx86_64_init_local c-int( 33 | cursor unw_cursor_t mut*, 34 | context unw_context_t mut*, 35 | ) unwind extern, pure 36 | -_ULx86_64_step c-int(cursor unw_cursor_t mut*) unwind extern, pure 37 | -_ULx86_64_get_proc_name c-int( 38 | cursor unw_cursor_t mut*, 39 | begin c-char mut*, 40 | size size_t, 41 | offset unw_word_t mut*, 42 | ) unwind extern, pure 43 | -------------------------------------------------------------------------------- /src/test/testMutMultiMap.d: -------------------------------------------------------------------------------- 1 | module test.testMutMultiMap; 2 | 3 | @safe @nogc pure nothrow: 4 | 5 | import test.testUtil : Test; 6 | import util.alloc.alloc : Alloc, withTempAlloc; 7 | import util.col.mutMultiMap : add, countKeys, eachValueForKey, mayDeleteKey, mayDeletePair, MutMultiMap; 8 | 9 | void testMutMultiMap(ref Test test) { 10 | withTempAlloc!void(test.metaAlloc, (ref Alloc alloc) { 11 | testBasic(alloc); 12 | }); 13 | } 14 | 15 | private: 16 | 17 | void testBasic(ref Alloc alloc) { 18 | MutMultiMap!(uint, uint) a; 19 | 20 | add(alloc, a, 1, 11); 21 | add(alloc, a, 2, 21); 22 | add(alloc, a, 1, 12); 23 | add(alloc, a, 2, 22); 24 | assertValuesForKey(a, 1, [11, 12]); 25 | assertValuesForKey(a, 2, [21, 22]); 26 | assert(countKeys(a) == 2); 27 | 28 | bool deleted = mayDeletePair(a, 1, 11); 29 | assert(deleted); 30 | assertValuesForKey(a, 1, [12]); 31 | 32 | size_t i = 0; 33 | mayDeleteKey(a, 2, (uint x) { 34 | static immutable uint[] expected = [21, 22]; 35 | assert(x == expected[i]); 36 | i++; 37 | }); 38 | assertValuesForKey(a, 1, [12]); 39 | assertValuesForKey(a, 2, []); 40 | assert(countKeys(a) == 1); 41 | } 42 | 43 | void assertValuesForKey(in MutMultiMap!(uint, uint) a, uint key, in uint[] values) { 44 | size_t i = 0; 45 | eachValueForKey(a, key, (uint x) { 46 | assert(x == values[i]); 47 | i++; 48 | }); 49 | assert(i == values.length); 50 | } 51 | -------------------------------------------------------------------------------- /site-src/script/loading-spinner.crow: -------------------------------------------------------------------------------- 1 | import 2 | crow/js/dom 3 | 4 | define-loading-spinner-element void() summon, trusted, js extern 5 | "crow-loading-spinner" define-custom-element css, x => 6 | x.shadow-root ~= loading-div 7 | 8 | create-loading-spinner node() trusted, js extern 9 | "crow-loading-spinner" create-node 10 | 11 | -loading-div node() js extern 12 | "root" create-div for class-name : ("child-0", "child-1", "child-2", "child-3")::string[] 13 | class-name create-div 14 | 15 | -css string() 16 | """ 17 | .root \{ 18 | display: inline-block; 19 | position: relative; 20 | height: 2em; 21 | } 22 | .child-0, .child-1, .child-2, .child-3 \{ 23 | position: absolute; 24 | top: 0.75em; 25 | width: 0.666em; 26 | height: 0.666em; 27 | border-radius: 50%; 28 | background: #ab9df2; 29 | animation-timing-function: cubic-bezier(0, 1, 1, 0); 30 | } 31 | .child-0 \{ left: 1em; animation: ani0 0.8s infinite; } 32 | .child-1 \{ left: 1em; animation: ani1 0.8s infinite; } 33 | .child-2 \{ left: 2em; animation: ani1 0.8s infinite; } 34 | .child-3 \{ left: 3em; animation: ani2 0.8s infinite; } 35 | @keyframes ani0 \{ 36 | 0% \{ transform: scale(0); } 37 | 100% \{ transform: scale(1); } 38 | } 39 | @keyframes ani1 \{ 40 | 0% \{ transform: translate(0, 0); } 41 | 100% \{ transform: translate(1em, 0); } 42 | } 43 | @keyframes ani2 \{ 44 | 0% \{ transform: scale(1); } 45 | 100% \{ transform: scale(0); } 46 | } 47 | """ 48 | -------------------------------------------------------------------------------- /src/util/col/mutSet.d: -------------------------------------------------------------------------------- 1 | module util.col.mutSet; 2 | 3 | @safe @nogc pure nothrow: 4 | 5 | import util.alloc.alloc : Alloc; 6 | import util.col.hashTable : getOrAdd, mayAdd, mayDelete, MutHashTable; 7 | import util.opt : has, MutOpt; 8 | 9 | struct MutSet(T) { 10 | @safe @nogc pure nothrow: 11 | private MutHashTable!(T, T, getKey) inner; 12 | 13 | MutSet!T move() { 14 | MutSet!T res = MutSet!T(inner); 15 | inner = MutHashTable!(T, T, getKey)(); 16 | return res; 17 | } 18 | 19 | bool opBinaryRight(string op)(in T x) scope const if (op == "in") => 20 | x in inner; 21 | 22 | int opApply(in int delegate(ref T) @safe @nogc pure nothrow cb) scope => 23 | inner.opApply(cb); 24 | int opApply(in int delegate(ref const T) @safe @nogc pure nothrow cb) scope const => 25 | inner.opApply(cb); 26 | } 27 | 28 | private ref T getKey(T)(ref T x) => x; 29 | 30 | bool mayAddToMutSet(T)(ref Alloc alloc, scope ref MutSet!T a, T value) => 31 | mayAdd(alloc, a.inner, value); 32 | 33 | T getOrAddLazyAlloc(T)( 34 | ref Alloc alloc, 35 | ref MutSet!T a, 36 | in T value, 37 | in T delegate() @safe @nogc pure nothrow allocValue, 38 | ) => 39 | getOrAdd!(T, T, getKey)(alloc, a.inner, value, () { 40 | T res = allocValue(); 41 | assert(res == value); 42 | return res; 43 | }); 44 | 45 | bool mutSetMayDelete(T)(scope ref MutSet!T a, T value) { 46 | MutOpt!T deleted = mayDelete(a.inner, value); 47 | return has(deleted); 48 | } 49 | -------------------------------------------------------------------------------- /test/dependencies.crow: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env crow 2 | import 3 | crow/io/file: write-file 4 | crow/io/process: shell-exec 5 | ../site-src/search-dir-recursive: search-dir-recursive 6 | 7 | main void() summon, native extern 8 | files = "src" search-dir-recursive x => x ends-with ".d" 9 | dependencies dependency[] = with out : build 10 | for file : files 11 | importer = file module-from-path 12 | guard importer !ignore 13 | for x : file imports 14 | guard x !ignore 15 | out ~= (importer, x) 16 | "bin/dependencies.dot" write-file dependencies.to-dot 17 | () 18 | 19 | -imports string[](file string) summon, native extern 20 | "dub run dscanner --yes --quiet -- --imports {file}".shell-exec split "\n" filter x => 21 | x != "" && x !starts-with "core." 22 | 23 | -module-from-path string(a string) 24 | a try-remove-start! "src/" try-remove-end! ".d" replace-all "/", "." 25 | 26 | -dependency record(importer string, exporter string) 27 | 28 | -to string(a dependency) 29 | "{a.importer.to::json} -> {a.exporter.to::json}" 30 | 31 | -ignore bool(a string) 32 | # omit model and util since these are commonly imported dependencies 33 | ignore-base string[] = "core.", "model.", "std.", "test.", "util." 34 | a == "object" || ignore-base exists (x => a starts-with x) || a ends-with ".txt" 35 | 36 | -to-dot string(dependencies dependency[]) 37 | """digraph crow \{ 38 | {";\n\t" join for x : dependencies; x.to} 39 | }""" 40 | -------------------------------------------------------------------------------- /include/crow/col/experimental/hamt-set.crow: -------------------------------------------------------------------------------- 1 | no-std 2 | import 3 | ../../bool: bool, not 4 | ../../fun-util: subscript 5 | ../../misc: key, new, void 6 | ../../number: nat64 7 | ../../option: ??, is-empty, new, option 8 | ../../tuple: a, b, new 9 | ../array: array, iterate, size 10 | ../collection: for-loop 11 | ../map: ~=, build, get-or-add, is-empty, iterate, map, size, subscript, try-remove 12 | 13 | +hamt-set[t] record 14 | -inner void[t] 15 | 16 | +new[t] t hamt-set(...values t[]) t key 17 | values to 18 | 19 | +to[t] t hamt-set(a t[]) t key 20 | inner void[t] = for x : a; x, () 21 | inner, 22 | 23 | +is-empty[t] bool(a t hamt-set) t key 24 | a.inner is-empty 25 | 26 | +size[t] nat64(a t hamt-set) t key 27 | a.inner size 28 | 29 | +in[t] bool(value t, a t hamt-set) t key 30 | a.inner[value] !is-empty 31 | 32 | + ~[t] t hamt-set(a t hamt-set, value t) t key 33 | a try-add value ?? a 34 | 35 | +try-add[t] t hamt-set?(a t hamt-set, value t) t key 36 | match a.inner get-or-add value, () => () 37 | as got _ 38 | () 39 | as added res 40 | (res.a,), 41 | 42 | + -[t] t hamt-set(a t hamt-set, value t) t key 43 | a try-remove value ?? a 44 | 45 | +try-remove[t] t hamt-set?(a t hamt-set, value t) t key 46 | if res ?= a.inner try-remove value 47 | (res.b,), 48 | 49 | region spec impls (see collection.crow) 50 | 51 | +iterate[t] bool(a t hamt-set, f bool mut(elem t)) t key 52 | a.inner iterate (k, _) => f[k] 53 | -------------------------------------------------------------------------------- /include/crow/io/duration.crow: -------------------------------------------------------------------------------- 1 | no-std 2 | import 3 | ../compare: >= 4 | ../number: ==, <=>, *, /, float64 5 | ../string: interpolate, show, string 6 | 7 | # Represents an amount of time. 8 | +duration record by-val 9 | -nanos float64 10 | 11 | # 0 duration. 12 | +new duration() 13 | 0, 14 | 15 | # Duration of `a` seconds. 16 | +second duration(a float64) 17 | a * 1_000_000_000, 18 | 19 | # Duration of `a` milliseconds. 20 | +millisecond duration(a float64) 21 | a * 1000000, 22 | 23 | # Duration of `a` microseconds. 24 | +microsecond duration(a float64) 25 | a * 1000, 26 | 27 | # Duration of `a` nanoseconds. 28 | +nanosecond duration(a float64) 29 | a, 30 | 31 | # Number of seconds in `a`. 32 | +seconds float64(a duration) 33 | a.nanos / 1_000_000_000 34 | 35 | # Number of milliseconds in `a`. 36 | +milliseconds float64(a duration) 37 | # TODO:ROUND 38 | a.nanoseconds / 1_000_000 39 | 40 | # Number of microseconds in `a`. 41 | +microseconds float64(a duration) 42 | # TODO:ROUND 43 | a.nanoseconds / 1000 44 | 45 | # Number of nanoseconds in `a`. 46 | +nanoseconds float64(a duration) 47 | a nanos 48 | 49 | # Tries to pick an appropriate format for the value, like `1.5s` or `2.3us`. 50 | +show string(a duration) 51 | if a.nanos >= 1_000_000_000 52 | "{a seconds}s" 53 | elif a.nanos >= 1_000_000 54 | "{a milliseconds}ms" 55 | elif a.nanos >= 1_000 56 | "{a microseconds}us" 57 | else 58 | "{a nanoseconds}ns" 59 | -------------------------------------------------------------------------------- /src/test/testWriter.d: -------------------------------------------------------------------------------- 1 | module test.testWriter; 2 | 3 | @safe @nogc pure nothrow: 4 | 5 | import test.testUtil : assertEqual, Test; 6 | import util.writer : withStackWriter, writeFloatLiteralForC, writeQuotedString, Writer; 7 | 8 | void testWriter(ref Test test) { 9 | testFloatLiteralForC(); 10 | testQuotedString(); 11 | } 12 | 13 | private: 14 | 15 | void testFloatLiteralForC() { 16 | void writes(double value, string expected) { 17 | withStackWriter!0x1000( 18 | (scope ref Writer writer) { 19 | writeFloatLiteralForC(writer, value); 20 | }, 21 | (in string actual) { 22 | assertEqual(actual, expected); 23 | }); 24 | } 25 | 26 | writes(double.nan, "NAN"); 27 | writes(double.infinity, "INFINITY"); 28 | writes(-double.infinity, "-INFINITY"); 29 | writes(-0.0, "-0"); 30 | writes(0.0, "0"); 31 | writes(123, "123"); 32 | writes(-123, "-123"); 33 | writes(1.2, "1.2"); 34 | writes(-1.2, "-1.2"); 35 | writes(1.23, "0x1.3ae147ae147aep0"); 36 | writes(-1.23, "-0x1.3ae147ae147aep0"); 37 | writes(0.75, "0x1.8000000000000p-1"); 38 | writes(0.001, "0x1.0624dd2f1a9fcp-10"); 39 | } 40 | 41 | void testQuotedString() { 42 | void writes(string value, string expected) { 43 | withStackWriter!0x1000( 44 | (scope ref Writer writer) { 45 | writeQuotedString(writer, value); 46 | }, 47 | (in string actual) { 48 | assertEqual(actual, expected); 49 | }); 50 | } 51 | 52 | writes("$¥₿𝄮", "\"$¥₿𝄮\""); 53 | } 54 | -------------------------------------------------------------------------------- /demo/webapp/model.crow: -------------------------------------------------------------------------------- 1 | import 2 | crow/crypto/experimental/login-cookie: login-cookie, show 3 | crow/parse 4 | 5 | register-args record(user-name string, password string) 6 | to json(a register-args) 7 | to register-args(a json) 8 | a["user-name"].string!, a["password"].string! 9 | 10 | login-args alias 11 | register-args 12 | 13 | user-cookie record(user nat, inner login-cookie) 14 | user-cookie user-cookie grammar() 15 | nat ~~ "|" ~~ login-cookie map (user, cookie) => user, cookie 16 | show string(a user-cookie) 17 | "{a user}|{a inner}" 18 | 19 | post-args record(content string) 20 | to json(a post-args) 21 | to post-args(a json) 22 | a["content"].string!, 23 | 24 | post-response record(id post) 25 | to json(a post-response) 26 | to post-response(a json) 27 | a["id"].to, 28 | show string(a post-response) 29 | "Post id={a id}" 30 | 31 | user alias 32 | nat 33 | 34 | user-info record(user user, user-name string) 35 | to json(a user-info) 36 | to user-info(a json) 37 | a["user"].to, a["user-name"].string! 38 | show string(a user-info) 39 | "User id={a user} name={a user-name}" 40 | 41 | post alias 42 | nat 43 | 44 | post-info record(post post, user user, user-name string, content string) 45 | to json(a post-info) 46 | to post-info(a json) 47 | a["post"].to, a["user"].to, a["user-name"].string!, a["content"].string! 48 | show string(a post-info) 49 | "Post id={a post} user-id={a user} user-name{a user-name} content={a content}" 50 | --------------------------------------------------------------------------------