├── .bazelrc ├── .bazelversion ├── .gitignore ├── .moonlark.d ├── .gitignore └── README.txt ├── .obazlrc ├── .sunlark.d ├── .gitignore └── README.txt ├── BUILD.bazel ├── BUILD.bzl ├── LICENSE ├── MODULE.bazel ├── README.md ├── WORKSPACE.bazel ├── bzl ├── host │ └── BUILD.bazel ├── tools │ ├── BUILD.bazel │ ├── aliases │ ├── copy.sh │ ├── lemon-mode.el │ ├── lsws │ ├── lwsw-completion.bash │ └── wss └── user.bazelrc ├── doc ├── devguide.md └── sunlark.md ├── src ├── BUILD.bazel ├── BUILD.bzl ├── constants.c ├── expressors.c ├── lexis.re ├── sealark_binding_mutators.c ├── sealark_bindings.c ├── sealark_ctors.c ├── sealark_debug.c ├── sealark_dictionaries.c ├── sealark_errors.c ├── sealark_format.c ├── sealark_loadstmts.c ├── sealark_loadstmts_set.c ├── sealark_mutators.c ├── sealark_nodes.c ├── sealark_package.c ├── sealark_parsers.c ├── sealark_predicators.c ├── sealark_procs.c ├── sealark_serializers.c ├── sealark_targets.c ├── sealark_vectors.c └── syntaxis.y └── test ├── BUILD.bazel ├── data ├── BUILD.bazel ├── BUILD.binding_get ├── android │ ├── BUILD.bazel │ └── BUILD.test ├── brstrings.BUILD ├── cc │ ├── BUILD.bazel │ └── BUILD.test ├── comments │ ├── BUILD.abseil │ ├── BUILD.bazel │ ├── BUILD.shell_command │ ├── BUILD.test │ ├── BUILD.test1 │ └── BUILD.test2 ├── dictionaries │ ├── BUILD.actions_run │ ├── BUILD.bazel │ ├── BUILD.test1 │ └── BUILD.test2 ├── filegroup │ ├── BUILD.bazel │ └── BUILD.test ├── genrules │ ├── BUILD.bazel │ ├── BUILD.lib_sexp │ └── BUILD.test1 ├── java │ ├── BUILD.bazel │ ├── BUILD.native │ ├── BUILD.skylark │ └── BUILD.test ├── large │ ├── BUILD.bazel │ └── BUILD.test ├── load │ ├── BUILD.args │ ├── BUILD.bazel │ ├── BUILD.test1 │ ├── BUILD.test2 │ ├── BUILD.testsq │ ├── aliases │ │ ├── test1 │ │ │ ├── BUILD.bazel │ │ │ └── BUILD.test │ │ └── test2 │ │ │ ├── BUILD.bazel │ │ │ └── BUILD.test │ ├── comments │ │ ├── BUILD.bazel │ │ └── BUILD.test │ ├── test2 │ │ ├── BUILD.bazel │ │ └── BUILD.test │ └── test3 │ │ ├── BUILD.bazel │ │ └── BUILD.test ├── ocaml │ ├── BUILD.bazel │ └── BUILD.test1 ├── python │ ├── BUILD.bazel │ ├── BUILD.test │ └── native │ │ ├── BUILD.bazel │ │ └── BUILD.test ├── shell │ ├── BUILD.bazel │ └── BUILD.test ├── small │ ├── BUILD.bazel │ ├── BUILD.test1 │ ├── BUILD.test2 │ └── BUILD.test3 ├── sunlark │ ├── BUILD.bazel │ └── BUILD.test ├── walk │ ├── BUILD.bazel │ ├── BUILD.complete │ ├── BUILD.exports │ ├── BUILD.load1 │ ├── BUILD.load2 │ ├── BUILD.load3 │ ├── BUILD.load4 │ ├── BUILD.mix1 │ ├── BUILD.package │ ├── BUILD.targets1 │ ├── BUILD.targets2 │ ├── BUILD.targets3 │ ├── BUILD.targets4 │ ├── BUILD.targets5 │ ├── BUILD.test2 │ └── BUILD.test3 └── windows │ └── dll │ ├── BUILD.bazel │ └── BUILD.test ├── lex_file.c ├── parse_file.c ├── sys ├── BUILD.bazel ├── starlark_roundtrip.c └── test_starlark.c └── unit ├── parser ├── BUILD.bazel ├── lex_keywords.c ├── lex_misc.c ├── lex_numbers.c ├── lex_punctuation.c ├── lex_strings.c ├── syntax_call_expr.c ├── syntax_dict.c ├── syntax_expressions.c ├── syntax_lists.c ├── syntax_slices.c └── syntax_statements.c └── sealark ├── BUILD.bazel └── buildfile_expressors.c /.bazelrc: -------------------------------------------------------------------------------- 1 | common --incompatible_enable_cc_toolchain_resolution 2 | always --experimental_cc_shared_library 3 | 4 | always --enable_bzlmod 5 | common --registry=https://raw.githubusercontent.com/obazl/registry/main/ 6 | common --registry=https://bcr.bazel.build 7 | 8 | ## for parser testing, data file won't be read without this. why??? 9 | #build --nobuild_runfile_links 10 | 11 | # test --//src:yydebug=dicts,vectors,targets,loads 12 | 13 | try-import %workspace%/.config/user.bazelrc 14 | -------------------------------------------------------------------------------- /.bazelversion: -------------------------------------------------------------------------------- 1 | latest -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .bazelignore 2 | .bazeliskrc 3 | .bazelversion 4 | bazel-* 5 | .bazel 6 | test.BUILD.bazel 7 | *.log 8 | log.* 9 | tmp/ 10 | test/data/tmp 11 | .sunlark.d 12 | obsolete 13 | 14 | gtags.files 15 | GPATH 16 | GRTAGS 17 | GTAGS 18 | 19 | # Prerequisites 20 | *.d 21 | 22 | # Object files 23 | *.o 24 | *.ko 25 | *.obj 26 | *.elf 27 | 28 | # Linker output 29 | *.ilk 30 | *.map 31 | *.exp 32 | 33 | # Precompiled Headers 34 | *.gch 35 | *.pch 36 | 37 | # Libraries 38 | *.lib 39 | *.a 40 | *.la 41 | *.lo 42 | 43 | # Shared objects (inc. Windows DLLs) 44 | *.dll 45 | *.so 46 | *.so.* 47 | *.dylib 48 | 49 | # Executables 50 | *.exe 51 | *.out 52 | *.app 53 | *.i*86 54 | *.x86_64 55 | *.hex 56 | 57 | # Debug files 58 | *.dSYM/ 59 | *.su 60 | *.idb 61 | *.pdb 62 | 63 | # Kernel Module Compile Results 64 | *.mod* 65 | *.cmd 66 | .tmp_versions/ 67 | modules.order 68 | Module.symvers 69 | Mkfile.old 70 | dkms.conf 71 | -------------------------------------------------------------------------------- /.moonlark.d/.gitignore: -------------------------------------------------------------------------------- 1 | * -------------------------------------------------------------------------------- /.moonlark.d/README.txt: -------------------------------------------------------------------------------- 1 | Moonlark will automatically add `/.moonlark.d/` (where 2 | is the project root directory) to the Lua load path. 3 | 4 | In the Sealark repo, this directory and this file are under version 5 | control for documentation purposes. But other contents are gitignored, 6 | so it can be used to test Lua code during Sealark development. Do 7 | not check in any other files in this directory. 8 | 9 | -------------------------------------------------------------------------------- /.obazlrc: -------------------------------------------------------------------------------- 1 | ; obazl config 2 | 3 | [obazl] 4 | version = 0.1.0 5 | grammar=1.0.0-BETA ;; version number of config grammar, not obazl program 6 | 7 | [srcs] 8 | 9 | dirs = src 10 | 11 | [watch] 12 | 13 | dirs = data tmp 14 | dirs = src 15 | dirs = watch 16 | 17 | ;; repos = coq_equations coq-simple-io ocaml-containers ocaml-ctypes 18 | 19 | ;; [repos] 20 | ;; coq = coq_equations coq-simple-io 21 | ;; ocaml = ocaml-containers ocaml-ctypes 22 | 23 | ;; [repo:coq_sdk] ;; get this info from .coqrc files? 24 | ;; coqpath = theories user-contrib/Ltac2 25 | ;; ocamlpath = clib lib theories user-contrib/Ltac2 ;; etc. 26 | 27 | ;; [repo:coq_equations] 28 | ;; ;; coqpath = theories 29 | ;; ;; ocamlpath = src 30 | 31 | ;; [ocamllibs] 32 | ;; ofoo = $HOME/o/foo 33 | ;; obar = $HOME/o/bar 34 | 35 | ;; [ocamlopts] 36 | ;; mllib1 = opt1 opt2 opt3 37 | ;; mllib2 = opt1 opt2 opt3 38 | ;; module1 = opt1 opt2 opt3 39 | ;; module2 = opt1 opt2 opt3 40 | 41 | ;; [coqlibs] 42 | ;; foo = $HOME/foo 43 | ;; bar = $HOME/bar 44 | -------------------------------------------------------------------------------- /.sunlark.d/.gitignore: -------------------------------------------------------------------------------- 1 | * -------------------------------------------------------------------------------- /.sunlark.d/README.txt: -------------------------------------------------------------------------------- 1 | Sunlark will automatically add `/.sunlark.d/` (where 2 | is the project root directory) to the Scheme (s7) load path. 3 | 4 | In the Sealark repo, this directory and this file are under version 5 | control for documentation purposes. But other contents are gitignored, 6 | so it can be used to test Scheme code during Sealark development. Do 7 | not check in any other files in this directory. 8 | 9 | -------------------------------------------------------------------------------- /BUILD.bazel: -------------------------------------------------------------------------------- 1 | load("@bazel_skylib//rules:common_settings.bzl", "string_list_flag") 2 | 3 | load("@obazl_tools_cc//rules:module_profiles.bzl", 4 | "module_profiles") 5 | 6 | PROD_REPOS = [ 7 | "@liblogc//src:logc", 8 | "@uthash//src:uthash" 9 | ] 10 | 11 | module_profiles( 12 | name = "module_profiles", 13 | repos = PROD_REPOS 14 | ) 15 | 16 | module_profiles( 17 | name = "test_module_profiles", 18 | repos = PROD_REPOS + [ 19 | "@unity//src:unity" 20 | ] 21 | ) 22 | 23 | 24 | string_list_flag(name = "debug", build_setting_default = []) 25 | config_setting(name = "debug-ast", flag_values = {":debug": "ast"}) 26 | config_setting(name = "debug-bindings", flag_values = {":debug": "bindings"}) 27 | config_setting(name = "debug-ctors", flag_values = {":debug": "ctors"}) 28 | config_setting(name = "debug-filters", flag_values = {":debug": "filters"}) 29 | config_setting(name = "debug-format", flag_values = {":debug": "format"}) 30 | config_setting(name = "debug-load", flag_values = {":debug": "load"}) 31 | config_setting(name = "debug-mem", flag_values = {":debug": "mem"}) 32 | config_setting(name = "debug-loads", flag_values = {":debug": "loads"}) 33 | config_setting(name = "debug-mutators", flag_values = {":debug": "mutators"}) 34 | config_setting(name = "debug-paths", flag_values = {":debug": "paths"}) 35 | config_setting(name = "debug-preds", flag_values = {":debug": "predicates"}) 36 | config_setting(name = "debug-properties", flag_values = {":debug": "properties"}) 37 | config_setting(name = "debug-queries", flag_values = {":debug": "queries"}) 38 | config_setting(name = "debug-s7-api", flag_values = {":debug": "s7-api"}) 39 | config_setting(name = "debug-serializers", flag_values = {":debug": "serializers"}) 40 | config_setting(name = "debug-set", flag_values = {":debug": "set"}) 41 | config_setting(name = "debug-targets", flag_values = {":debug": "targets"}) 42 | config_setting(name = "debug-trace", flag_values = {":debug": "trace"}) 43 | config_setting(name = "debug-utarrays", flag_values = {":debug": "utarrays"}) 44 | config_setting(name = "debug-vectors", flag_values = {":debug": "vectors"}) 45 | config_setting(name = "debug-yytrace", flag_values = {":debug": "yytrace"}) 46 | 47 | -------------------------------------------------------------------------------- /BUILD.bzl: -------------------------------------------------------------------------------- 1 | debug_defs = select({ 2 | "//:debug-ast": ["DEBUG_AST"], 3 | "//conditions:default": [] 4 | }) + select({ 5 | "//:debug-bindings": ["DEBUG_BINDINGS"], 6 | "//conditions:default": [] 7 | }) + select({ 8 | "//:debug-ctors": ["DEBUG_CTORS"], 9 | "//conditions:default": [] 10 | }) + select({ 11 | "//:debug-filters": ["DEBUG_FILTERS"], 12 | "//conditions:default": [] 13 | }) + select({ 14 | "//:debug-format": ["DEBUG_FORMAT"], 15 | "//conditions:default": [] 16 | }) + select({ 17 | "//:debug-load": ["DEBUG_LOAD"], 18 | "//conditions:default": [] 19 | }) + select({ 20 | "//:debug-loads": ["DEBUG_LOADS"], 21 | "//conditions:default": [] 22 | }) + select({ 23 | "//:debug-mem": ["DEBUG_MEM"], 24 | "//conditions:default": [] 25 | }) + select({ 26 | "//:debug-mutators": ["DEBUG_MUTATORS"], 27 | "//conditions:default": [] 28 | }) + select({ 29 | "//:debug-paths": ["DEBUG_PATHS"], 30 | "//conditions:default": [] 31 | }) + select({ 32 | "//:debug-preds": ["DEBUG_PREDICATES"], 33 | "//conditions:default": [] 34 | }) + select({ 35 | "//:debug-properties": ["DEBUG_PROPERTIES"], 36 | "//conditions:default": [] 37 | }) + select({ 38 | "//:debug-queries": ["DEBUG_QUERY"], 39 | "//conditions:default": [] 40 | }) + select({ 41 | "//:debug-s7-api": ["DEBUG_S7_API"], 42 | "//conditions:default": [] 43 | }) + select({ 44 | "//:debug-set": ["DEBUG_SET"], 45 | "//conditions:default": [] 46 | }) + select({ 47 | "//:debug-serializers": ["DEBUG_SERIALIZERS"], 48 | "//conditions:default": [] 49 | }) + select({ 50 | "//:debug-targets": ["DEBUG_TARGETS"], 51 | "//conditions:default": [] 52 | }) + select({ 53 | "//:debug-trace": ["DEBUG_TRACE"], 54 | "//conditions:default": [] 55 | }) + select({ 56 | "//:debug-utarrays": ["DEBUG_UTARRAYS"], 57 | "//conditions:default": [] 58 | }) + select({ 59 | "//:debug-vectors": ["DEBUG_VECTORS"], 60 | "//conditions:default": [] 61 | }) + select({ 62 | "//:debug-yytrace": ["DEBUG_YYTRACE"], 63 | "//conditions:default": [] 64 | }) 65 | 66 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2021 obazl 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /MODULE.bazel: -------------------------------------------------------------------------------- 1 | module( 2 | name = "sealark", 3 | version = "1.0.0", 4 | compatibility_level = 1, 5 | bazel_compatibility = [">=6.0.0"] 6 | ) 7 | 8 | ## bcr deps: 9 | bazel_dep(name = "platforms", version = "0.0.7") 10 | bazel_dep(name = "bazel_skylib", version = "1.4.2") 11 | bazel_dep(name = "rules_cc", version = "0.0.9") 12 | bazel_dep(name = "rules_foreign_cc", version = "0.9.0") 13 | 14 | ## sfsexp, libinih, re2c, fswatch, unity, libffi 15 | ## stardoc 16 | 17 | 18 | ## obazl deps: 19 | bazel_dep(name = "obazl_tools_cc", version = "1.0.0") 20 | bazel_dep(name = "inih", version = "57.0.0") 21 | bazel_dep(name = "lemon", version = "3.42.0") 22 | bazel_dep(name = "liblogc", version = "1.0.0") 23 | bazel_dep(name = "makeheaders", version = "1.0.2") 24 | bazel_dep(name = "re2c", version = "3.1.0") 25 | 26 | bazel_dep(name = "fswatch", version = "1.17.1") 27 | bazel_dep(name = "libffi", version = "3.4.4") 28 | bazel_dep(name = "sfsexp", version = "1.4.1") 29 | 30 | bazel_dep(name = "gopt", version = "10.0.0", 31 | dev_dependency=True) 32 | bazel_dep(name = "unity", version = "2.5.2", 33 | dev_dependency=True) 34 | bazel_dep(name = "uthash", version = "2.3.0", 35 | dev_dependency=True) 36 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Sealark - tools for Starlark parsing and editing 2 | Sealark is a collection of tools for working with Starlark code, 3 | written in C (get it, C-lark?). `libsealark` is a Starlark parser; 4 | [Sunlark](https://github.com/obazl/sunlark) is a Scheme binding; 5 | [Moonlark](https://github.com/obazl/moonlark) is a Lua binding; 6 | 7 | [List of lark species](https://en.wikipedia.org/wiki/List_of_lark_species). Sunlark is actually a [species](https://en.wikipedia.org/wiki/Sun_lark). 8 | 9 | **STATUS** Beta-ish. Used by 10 | [Sunlark](https://github.com/obazl/sunlark); documentation is on the 11 | way. 12 | 13 | ## libsealark 14 | 15 | `libsealark` is a C11 library that contains routines to parse files 16 | and strings of Starlark code, producing a simple AST. It also contains 17 | some serialization routines to write the AST to a string. The result 18 | can be compared to the original input. (The goal is a 100% match, 19 | including whitespace and comments). 20 | 21 | `libsealark` uses [re2c](https://re2c.org/) for lexing, 22 | [lemon](https://www.sqlite.org/cgi/src/doc/trunk/doc/lemon.html) for 23 | parsing, and [uthash](https://troydhanson.github.io/uthash/) for C 24 | data structures. Experienced C programmers will notice there are no 25 | header (.h) files in the source tree. That's because it uses 26 | [Makeheaders](https://fossil-scm.org/home/doc/trunk/src/makeheaders.html#H0009), 27 | which automatically generates one header for each source file, 28 | containing everything it needs (and nothing more). Each BUILD.bazel 29 | file contains a `:mkhdrs` target that runs `makeheaders`. In addition 30 | `sealark/BUILD.bazel` has a `:mkhdrs-export` that generates the 31 | `sealark.h` public API. 32 | 33 | Currently `libsealark` does not contain a public API for manipulating 34 | the AST. A developer could easily implement such routines, however, 35 | since the AST is pretty simple, and it uses `utarray` and `utstring` 36 | from the [UTHash](https://troydhanson.github.io/uthash/) library. 37 | 38 | Instead, the parsing routines of `libsealark` are exposed in 39 | `sunlark`, a Scheme binding, which also exposes the parsed AST. AST 40 | manipulation and serialization can then be implemented in Scheme code. 41 | The idea is that this will make customization much easier, thus 42 | enabling tool makers to build a variety of tools on top of 43 | sunlark/sealark. Default implementations are provided, but the 44 | user can easily supply alternatives. 45 | 46 | A Lua binding, [Moonlark](https://github.com/obazl/moonlark), is 47 | partially implemented. 48 | 49 | ## testing 50 | 51 | ``` 52 | $ bazel run test:lex_file -- -f path/to/BUILD 53 | ``` 54 | 55 | ``` 56 | $ bazel run test:parse_file -- -f path/to/BUILD 57 | ``` 58 | 59 | Unit tests are currently in [Sunlark](https://github.com/obazl/sunlark/tree/main/test/unit/sunlark). 60 | -------------------------------------------------------------------------------- /WORKSPACE.bazel: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/obazl/sealark/d16062b113097d18d5e84f5247d916e7bc8f02c3/WORKSPACE.bazel -------------------------------------------------------------------------------- /bzl/host/BUILD.bazel: -------------------------------------------------------------------------------- 1 | package(default_visibility = ["//visibility:public"]) 2 | 3 | config_setting( 4 | name = "debug", 5 | values = {"compilation_mode": "dbg"}, 6 | ) 7 | 8 | ################################################################ 9 | config_setting( 10 | name = "linux", 11 | constraint_values = [ 12 | "@platforms//os:linux", 13 | ] 14 | ) 15 | 16 | config_setting( 17 | name = "linux_x64", 18 | constraint_values = [ 19 | "@platforms//os:linux", 20 | "@platforms//cpu:x86_64", 21 | ] 22 | ) 23 | 24 | config_setting( 25 | name = "linux_debug", 26 | constraint_values = ["@platforms//os:linux"], 27 | values = { 28 | "compilation_mode": "dbg", 29 | }, 30 | ) 31 | 32 | config_setting( 33 | name = "linux_opt", 34 | constraint_values = ["@platforms//os:linux"], 35 | values = { 36 | "compilation_mode": "opt" 37 | }, 38 | ) 39 | 40 | config_setting( 41 | name = "linux_fastbuild", 42 | constraint_values = ["@platforms//os:linux"] 43 | ) 44 | 45 | ################################################################ 46 | config_setting( 47 | name = "macos", 48 | constraint_values = ["@platforms//os:macos"] 49 | ) 50 | 51 | ## FIXME: should be based on compiler, not os, e.g. clang_debug v. gcc_debug 52 | ## @local_config_cc//:cc-compiler-darwin_x86_64 53 | config_setting( 54 | name = "macos_debug", 55 | constraint_values = [ 56 | # "@local_config_cc//:cc-compiler-darwin_x86_64" 57 | "@platforms//os:macos" 58 | ], 59 | values = { 60 | # "@bazel_tools//tools/cpp:toolchain_type": "@local_config_cc//:cc-compiler-darwin_x86_64", 61 | "compilation_mode": "dbg" 62 | }, 63 | ) 64 | 65 | config_setting( 66 | name = "macos_opt", 67 | constraint_values = ["@platforms//os:macos"], 68 | values = {"compilation_mode": "opt"} 69 | ) 70 | 71 | config_setting( 72 | name = "macos_fastbuild", 73 | constraint_values = ["@platforms//os:macos"] 74 | ) 75 | 76 | config_setting( 77 | name = "m32", 78 | constraint_values = [ 79 | "@platforms//cpu:x86_32", 80 | ] 81 | ) 82 | 83 | config_setting( 84 | name = "m64", 85 | constraint_values = [ 86 | "@platforms//cpu:x86_64", 87 | ] 88 | ) 89 | -------------------------------------------------------------------------------- /bzl/tools/BUILD.bazel: -------------------------------------------------------------------------------- 1 | 2 | exports_files(["copy.sh"]) 3 | -------------------------------------------------------------------------------- /bzl/tools/aliases: -------------------------------------------------------------------------------- 1 | # source me 2 | alias "bl=less `bazel info command_log`" -------------------------------------------------------------------------------- /bzl/tools/copy.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | cp $@ 4 | -------------------------------------------------------------------------------- /bzl/tools/lemon-mode.el: -------------------------------------------------------------------------------- 1 | ;;; lemon-mode.el --- A major mode for editing lemon grammar files 2 | 3 | ;; Copyright (C) 2012, 2013 mooz 4 | 5 | ;; Author: mooz 6 | ;; Version: 0.0.1 7 | ;; Keywords: lemon 8 | 9 | ;; This program is free software; you can redistribute it and/or modify 10 | ;; it under the terms of the GNU General Public License as published by 11 | ;; the Free Software Foundation, either version 3 of the License, or 12 | ;; (at your option) any later version. 13 | 14 | ;; This program is distributed in the hope that it will be useful, 15 | ;; but WITHOUT ANY WARRANTY; without even the implied warranty of 16 | ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17 | ;; GNU General Public License for more details. 18 | 19 | ;; You should have received a copy of the GNU General Public License 20 | ;; along with this program. If not, see . 21 | 22 | ;;; Commentary: 23 | 24 | ;; A major mode for editing LEMON Parser Generator grammar files. 25 | ;; 26 | ;; Lemon is a simple but very 27 | ;; powerful parser generator for C/C++. This major mode helps you edit 28 | ;; Lemon's grammar files in Emacs. 29 | ;; 30 | ;; lemon-mode.el provides two major modes (1) `lemon-c-mode' and (2) 31 | ;; `lemon-c++-mode', which allow you to explicitly specify the base 32 | ;; editing mode. The base editing mode affects syntax highlighting and 33 | ;; indentation mechanism. 34 | ;; 35 | 36 | ;;; Code: 37 | 38 | (require 'font-lock) 39 | (require 'cc-mode) 40 | 41 | ;; Misc variables 42 | 43 | (defvar lemon-base-mode) 44 | 45 | ;; Syntax highlight support 46 | 47 | (defvar lemon-syntax-capture "([A-Z][A-Z0-9]*)") 48 | 49 | (defvar lemon-syntax-terminal-symbol 50 | (concat "\\([A-Z][a-zA-Z_]*\\)[ \t]*\\(" lemon-syntax-capture "\\)?")) 51 | 52 | (defvar lemon-syntax-non-terminal-symbol 53 | (concat "\\([a-z][a-z0-9_]*\\)[ \t]*\\(" lemon-syntax-capture "\\)?")) 54 | 55 | (defvar lemon-syntax-lhs-symbol-value "\\$\\$") 56 | 57 | (defvar lemon-syntax-rhs-symbol-value "\\$[1-9][0-9]*") 58 | 59 | (defvar lemon-syntax-directive "%[a-zA-Z_0-9]+") 60 | 61 | (defvar lemon-syntax-rule-lhs 62 | (concat "[ \t]*" lemon-syntax-non-terminal-symbol "[ \t]*")) 63 | 64 | (defvar lemon-syntax-rule-rhs 65 | (concat "\\(|\\|" lemon-syntax-terminal-symbol "\\|" lemon-syntax-non-terminal-symbol "\\|[ \t]\\)*[ \t]*\\.")) 66 | 67 | (defvar lemon-syntax-rule 68 | (concat lemon-syntax-rule-lhs "::=[ \t]*" lemon-syntax-rule-rhs)) 69 | 70 | (defvar lemon-font-lock-keywords 71 | `((,lemon-syntax-directive . font-lock-function-name-face) ; special directive 72 | (,lemon-syntax-lhs-symbol-value . font-lock-constant-face) ; $$ 73 | (,lemon-syntax-rhs-symbol-value . font-lock-variable-name-face) ; $1, $2, ... 74 | (,(concat lemon-syntax-rule-lhs "::=") (1 font-lock-variable-name-face t)))) 75 | 76 | ;; Indentation support 77 | 78 | (defun lemon-inside-block-p () 79 | "Returns true if `point' is placed between '{' and '}'" 80 | (save-excursion 81 | (let (parse-sexp-ignore-comments) 82 | (catch 'return 83 | (while t 84 | (unless (re-search-backward "\\({\\|}\\)" (point-min) t) 85 | (throw 'return nil)) 86 | (when (looking-at "{") 87 | (throw 'return t)) 88 | (goto-char (scan-lists (1+ (point)) -1 0))))))) 89 | 90 | (defun lemon-beginning-of-block () 91 | (when (lemon-inside-block-p) 92 | (and (re-search-backward "\\(\\.\\|\\[[A-Z_]+\\]\\|%[a-z_]+\\([ \t\n\r]+[a-z_]+\\)?\\)[ \t\n\r]*{" (point-min) t) 93 | (re-search-forward "{" (point-max) t) 94 | (backward-char)))) 95 | 96 | (defun lemon-indent-line (&optional syntax quiet ignore-point-pos) 97 | (cond 98 | ((lemon-inside-block-p) 99 | ;; Use C-style indentation 100 | (save-restriction 101 | (save-excursion 102 | (narrow-to-region (progn (lemon-beginning-of-block) (point)) 103 | (progn (forward-list) (point)))) 104 | (let ((major-mode lemon-base-mode)) 105 | (c-indent-line syntax quiet ignore-point-pos)))) 106 | (t 107 | ;; Otherwise, use lemon-style indentation 108 | ;; (FIXME: Currently, indentation is fixed to 0) 109 | (lemon-indent-line-lemon 0)))) 110 | 111 | (defun lemon-current-indentation () 112 | (save-excursion 113 | (back-to-indentation) 114 | (current-column))) 115 | 116 | (defun lemon-indent-line-lemon (column) 117 | (let ((offset (current-column)) 118 | (indentation-before (lemon-current-indentation))) 119 | (indent-line-to column) 120 | (let ((delta (- offset indentation-before))) 121 | (forward-char (max 0 delta))))) 122 | 123 | ;; Arrange keymap 124 | 125 | (defvar lemon-mode-map (make-sparse-keymap)) 126 | 127 | (defmacro lemon-define-derived-mode (base-mode base-mode-name) 128 | (let ((derived-mode 129 | (intern (concat "lemon-" (symbol-name base-mode)))) 130 | (derived-mode-name 131 | (concat "Lemon/" base-mode-name))) 132 | `(define-derived-mode ,derived-mode ,base-mode 133 | ,derived-mode-name 134 | "Major mode for editing lemon grammar files" 135 | (setq mode-name ,derived-mode-name) 136 | (setq major-mode (quote ,derived-mode)) 137 | ;; Indentation 138 | (make-local-variable 'indent-line-function) 139 | (setq indent-line-function 'lemon-indent-line) 140 | (make-local-variable 'indent-region-function) 141 | (setq indent-region-function nil) 142 | ;; Record base mode (for correct indentation) 143 | (make-local-variable 'lemon-derived-mode) 144 | (setq lemon-base-mode (quote ,base-mode)) 145 | ;; Keymap 146 | (use-local-map lemon-mode-map) 147 | ;; Syntax highlight 148 | (font-lock-add-keywords nil lemon-font-lock-keywords)))) 149 | 150 | (lemon-define-derived-mode c++-mode "C++") 151 | (lemon-define-derived-mode c-mode "C") 152 | 153 | (defalias 'lemon-mode 'lemon-c-mode) 154 | 155 | ;;;###autoload (autoload 'lemon-c++-mode "lemon-mode" nil t) 156 | ;;;###autoload (autoload 'lemon-c-mode "lemon-mode" nil t) 157 | ;;;###autoload (autoload 'lemon-mode "lemon-mode" nil t) 158 | 159 | (provide 'lemon-mode) 160 | ;;; lemon-mode.el ends here 161 | -------------------------------------------------------------------------------- /bzl/tools/lsws: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | if [[ $1 == "" ]]; then 4 | ls --color $(bazel info output_base)/external 5 | else 6 | ls --color $1 7 | fi 8 | 9 | exit 10 | -------------------------------------------------------------------------------- /bzl/tools/lwsw-completion.bash: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | while (( "$#" )); do 4 | case "$1" in 5 | -*|--*=) # flags 6 | FLAGS="$FLAGS $1" 7 | shift 8 | ;; 9 | *) # preserve positional arguments 10 | PARAMS="$PARAMS $1" 11 | shift 12 | ;; 13 | esac 14 | done 15 | 16 | # set positional arguments in their proper place 17 | eval set -- "$PARAMS" 18 | 19 | _comp_lsws() 20 | { 21 | local IFS=$' \t\n' # normalize IFS 22 | 23 | output_base="$(bazel info output_base)/external" 24 | 25 | if [[ $2 == "" ]]; then 26 | COMPREPLY=( $(compgen -W ${output_base} -- $2) ) 27 | else 28 | COMPREPLY=( $(compgen -d -- $2) ) 29 | COMPREPLY+=( $(compgen -f -- $2) ) 30 | fi 31 | 32 | return 0 33 | } 34 | 35 | complete -o filenames -o nospace -F _comp_lsws lsws 36 | -------------------------------------------------------------------------------- /bzl/tools/wss: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | for LAST; do true; done 4 | 5 | ARGS= 6 | for param in "$@" 7 | do 8 | ## echo COUNT: $# 9 | if [ $# -ne 1 ] 10 | then 11 | ARGS="$ARGS $1" 12 | fi 13 | shift 14 | done 15 | 16 | # if no dir arg is passed: 17 | if [[ $LAST == -* ]] 18 | then 19 | ARGS="$ARGS $LAST" 20 | LAST= 21 | fi 22 | 23 | ls --color $ARGS `bazel info output_base`/external/$LAST 24 | echo OUTPUT_BASE: `bazel info output_base`/external 25 | -------------------------------------------------------------------------------- /bzl/user.bazelrc: -------------------------------------------------------------------------------- 1 | # a sample user.config. put it in the root dir to use it (.bazelrc runs it) 2 | build --color=yes 3 | build --subcommands=pretty_print 4 | build --verbose_failures 5 | # build --sandbox_debug 6 | 7 | test --test_output=all 8 | 9 | build --//:debug=ast,s7-api,bindings,paths,queries,vectors,filters,targets,mutators,trace,set,properties,loads 10 | #,utarrays 11 | #,serializers 12 | #,predicates 13 | #,mem 14 | 15 | ## in .bazelrc: test --//sealark:yydebug=bindings,dicts,vectors 16 | 17 | run -c dbg 18 | -------------------------------------------------------------------------------- /doc/devguide.md: -------------------------------------------------------------------------------- 1 | # development 2 | 3 | **CAVEAT** Work-in-Progress. May not match source code. 4 | 5 | ## C 6 | 7 | ### makeheaders 8 | 9 | In many cases we need to run makeheaders against files in different 10 | packages. We expose them using `exports_files`. It is not sufficient 11 | to depend on the other library; the other library's exposed headers 12 | will be available, but the depending file, say `edit.c`, contains only 13 | `edit.h`, produced by makeheaders. So the other package's __source__ 14 | files must be included as input to the makeheaders command. 15 | 16 | Note that this does not affect the Bazel dependency graph, so circular 17 | dependencies will not be introduced. 18 | 19 | ## lua 20 | 21 | WARNING: outdated. lua support is moribund. 22 | 23 | Neither libsunlark nor libmoonlark depend on the Bazel environment. 24 | It's up to the app to deal with it. 25 | 26 | `//moonlark:edit` is a C application that depends on libmoonlark but 27 | not the moonlark Lua package. It is also Bazel-aware: it elaborates 28 | the Lua load path to include `//moonlark/lua` and the user Lua 29 | directory, which defaults to `//.moonlark.d`. It also accounts for the 30 | "runfiles" directory, which becomes the current directory when it is 31 | launched as `$ bazel run moonlark:edit`. It will set the Lua load path 32 | accordingly (which will include a hidden directory set up by Bazel) 33 | and then change directory to the original launch directory (which 34 | should be the root directory of a Bazel project.) Finally, it creates 35 | a global `bazel` table that contains useful subtables (e.g. 36 | `bazel.config` contains config info, `bazel.TOK` is a table of grammar 37 | constants, etc.; see X for details.) 38 | 39 | `//moonlark:repl` is a Lua interpreter with integrated moonlark 40 | support. The `moonlark` Lua package is preloaded. It is not 41 | Bazel-aware by default, but it comes with Lua code 42 | (`//moonlark/lua/repl.lua`) that can be used to configure it the way 43 | `//moonlark:edit` is configured. That code can be loaded by passing a 44 | command line argument, e.g. `$ bazel run moonlark:repl -- -i 45 | moonlark/lua/repl.lua`. 46 | 47 | [Alternative: the `moonlark` package exposes `config_bazel`, which 48 | will do same in C code.] 49 | 50 | ### initialization 51 | 52 | #### C apps 53 | 54 | Two options: with or without preconfigured Bazel integration. 55 | 56 | ##### With preconfigured Bazel support 57 | 58 | Startup code must set the load path and create the `bazel` table 59 | and subtables. It then calls a user-provided routine. 60 | 61 | Example: `moonlark/edit.c`. 62 | 63 | 1. Query the environment to compute the load paths and set the working directory. 64 | 65 | When `bazel run` is used to launch an executable, Bazel switches the 66 | current directory to a hidden "runfiles" directory in the sandbox. 67 | This means that opening relative filepaths may fail, unless you 68 | have configured things just so. Bazel exposes the original launch 69 | directory via the environment variables 70 | `BUILD_WORKSPACE_DIRECTORY` and `BUILD_WORKING_DIRECTORY`; see 71 | [Running 72 | executables](https://docs.bazel.build/versions/main/user-manual.html#run) 73 | for more information. 74 | 75 | This is an issue for two reasons. One is that you may want to 76 | `require` the lua files in `moonlark/lua` or `.moonlark.d`. The 77 | other is that you may want your Lua to read or write files. In the 78 | former case, you need to make sure the directories are on the Lua 79 | load path; in the latter case, you want to be able to use paths 80 | that are relative to the original launch directory. 81 | 82 | Furthermore, elaborating the Lua load path by simply adding a 83 | directory relative to the original launch directory (e.g. 84 | `moonlark/lua`) will not work when your repo is used as an 85 | external resource in another project. In that case, your project's 86 | code will only be available in a directory located in Bazel's 87 | hidden work area; you can see something of this by running `$ 88 | bazel info`. 89 | 90 | This is where "runfiles" enter the picture. If you know ahead of 91 | time that certain files may be accessed, you can designate them as 92 | "runfiles" by using the `data` attribute of the build rule. Bazel 93 | will use links to add such files to runfiles directory. That way 94 | your code can still reference such files using relative paths. For 95 | example, `data = ["//moonlark/lua:edit.lua"]` tells Bazel to add 96 | `moonlark/lua/edit.lua` to the runfiles directory. 97 | 98 | This is the strategy used by `//moonlark:edit` (and `//moonlark:repl`) - see the targets in `moonlark/BUILD.bazel`. 99 | 100 | However there is are a few complications. By making `moonlark/lua/edit.lua` a runfile, we could add `moonlark/lua` to 101 | the Lua load path, and then `require("edit")` would work. 102 | Unfortunately it would only work when run from this project root. 103 | If moonlark were added as an external repo to another project, it 104 | would fail, because in that case Bazel inserts directory segments 105 | "external/", so the Lua file would be available as 106 | `external/moonlark/moonlark/lua` (where the first 'moonlark' is 107 | the repo name). Secondly, since the current working directory 108 | would be the runfiles directory, accessing files in the original 109 | launch directory would require absolute paths, which is tedious 110 | and error-prone. 111 | 112 | To make a long story a bit shorter: what we need to do is the 113 | following (not necessarily in this order): 114 | 115 | A. Get the current working directory at startup (`getcwd()`); this 116 | will be the runfiles directory. 117 | 118 | B. Find and read the runfiles MANIFEST file; it will be in the 119 | parent directory. It contains mappings from runfiles to their 120 | locations; for example: 121 | 122 | moonlark/moonlark/lua/edit.lua /private/var/tmp/_bazel_gar/68...c637c/external/moonlark/moonlark/lua/edit.lua 123 | 124 | (We designated `moonlark/lua/edit.lua` as a runfile; the first 125 | 'moonlark' here is the directory name of the project root, which Bazel prefixes to get `moonlark/moonlark/lua/edit.lua`.) 126 | 127 | C. Start up the Lua runtime - `luaL_newstate()` 128 | 129 | D. Add the (absolute path of the) runfiles directory to the Lua load 130 | path; in this example that would be 131 | 132 | /private/var/tmp/_bazel_gar/68...c637c/external/moonlark/moonlark/lua 133 | 134 | By using an absolute path, we ensure that files in the directory 135 | can be `require`d no matter what the current working directory is. 136 | 137 | E. Add the user lua dir to the path. This must be relative to the 138 | original launch dir (i.e. proj root). We cannot designate user files 139 | as runfiles, so we need to check at runtime to see if `.moonlark.d` 140 | exists, and if so add it to the path. 141 | 142 | FIXME: support a config option/file allowing user to set custom lua dir 143 | 144 | F. Read env. var. `BUILD_WORKING_DIRECTORY`, which should be the 145 | original launch directory; then switch to it (`chdir(wd)`). 146 | 147 | 2. Create `bazel` table and subtables 148 | 149 | The `bazel` table contains fields: 150 | 151 | * `config`: list of configuration settings, e.g. project_root, 152 | runfiles_root, etc. 153 | 154 | * TOK - table mapping token name strings to codes, e.g. `bazel.TOK.LPAREN => 54` 155 | 156 | * iTOK - table mapping token codes to string names, e.g. `bazel.iTOK[54] => "LPAREN"` 157 | 158 | * pTOK - table mapping token codes to printable strings, e.g. 159 | `pTOK[bazel.TOK.LPAREN]` => "(" 160 | 161 | #### Without preconfigured Bazel support: 162 | 163 | ## Troubleshooting 164 | 165 | `/bin/bash: line 9: bindings/scheme/sunlark_properties.c: Permission denied` 166 | 167 | This is cause by a syntax error in a :mkhdrs target: 168 | 169 | ``` 170 | cmd = "\n".join([ 171 | "SRC1=$(location libsunlark.c)", 172 | "SRCDIR1=`dirname $$SRC1`", 173 | "$(location //vendored/makeheaders) \\", 174 | ...blah blah... 175 | " $(location ast_node_s7.c) \\", 176 | " $(location ast_nodelist_s7.c)", <<===== missing // before " 177 | " $(location sunlark_properties.c)", 178 | "cp $${SRCDIR1}/*.h $(@D)", 179 | ]), 180 | ``` 181 | 182 | WARNING: //vendored has been removed, see MODULE.bazel 183 | 184 | ## CAVEATS 185 | 186 | * Bazel may behave a little erratically when used as a launcher. The 187 | RUNFILES env. vars may or may not be defined, depending on whether 188 | run cmd was 'run' or 'test', and whether 'run' is used to launch a 189 | cc_binary or a cc_test target. Also, the runtime environments for 190 | the 'test' and 'run' commands are different. 191 | 192 | 193 | ### misc 194 | 195 | obsolete: 196 | 197 | generate tokens.h from tokens.txt (list of TOKEN names) 198 | 199 | rg -N . src/lib/obazl_starlark/tokens.txt | sort | uniq > toks.h 200 | nl -w 2 -n rz -s ' ' toks.h > toksnl.h 201 | 202 | paste -d ' ' toksnl.h toks.h | cut -d ' ' -f2,3 | sed 's/^/#define /' > src/lib/obazl/bazel/tokens.h 203 | 204 | generate tokens.c, with token_name lookup table 205 | 206 | sed 's/\(.*\)/[\1] = "\1",/' toks.h > src/lib/obazl_starlark/tokens.c 207 | 208 | 209 | -------------------------------------------------------------------------------- /doc/sunlark.md: -------------------------------------------------------------------------------- 1 | # sunlark 2 | 3 | Scheme bindings for libsealark. 4 | 5 | The implementationn is [s7]() 6 | 7 | ## generalized ref 8 | 9 | Example: 10 | 11 | Suppose `node` is a Sunlark ast-node representing a rule - a function 12 | application with a list of named arguments. The following two 13 | expressions are equivalent ways of getting the list: 14 | 15 | ``` 16 | (ast-node-ref node :attrs) 17 | (node :attrs) 18 | 19 | ``` 20 | 21 | The first is an ordinary Scheme function that calls implementation 22 | routine `sunlark_node_ref_specialized`, which interprets the args; in 23 | this case, it returns the attributes list of the node. 24 | 25 | The latter uses s7's object-applicator mechanism. `node` is an 26 | ast-node, which is a datum. But with s7 we can attach an "applicator" 27 | function to such a datum, which will be invoked with it occurs in a 28 | function-application context, e.g. as the car of a list as in this 29 | case. The object itself will be passed as the first argument, and the 30 | remaining elements of the list as the rest of the args. The 31 | implementation can then be designed to do whatever makes sense; in the 32 | case of Sunlark, we use this mechanism to support "pseudo" attributes 33 | such as `:attrs` and `:pprint`. 34 | -------------------------------------------------------------------------------- /src/BUILD.bzl: -------------------------------------------------------------------------------- 1 | def _gensyntax_impl(ctx): 2 | out_c = ctx.actions.declare_file("syntaxis.c") 3 | out_out = ctx.actions.declare_file("syntaxis.out") 4 | 5 | exe = ctx.file._tool.path 6 | 7 | # print(ctx.attr.defines) 8 | 9 | if (len(ctx.attr.defines) > 0): 10 | defs = "-D" + " -D".join(ctx.attr.defines) 11 | else: 12 | defs = "" 13 | 14 | cmd = "{lemon} -m {yy} {defines} -T{template} -d{outdir}".format( 15 | lemon=exe, yy=ctx.file.yy.path, 16 | defines=defs, 17 | template=ctx.file.template.path, 18 | outdir=out_c.dirname 19 | ) 20 | ctx.actions.run_shell( 21 | inputs = [ctx.file.yy, ctx.file.template], 22 | outputs = ctx.outputs.outs, 23 | tools = [ctx.file._tool], 24 | command = cmd 25 | ) 26 | 27 | return [DefaultInfo(files = depset(ctx.outputs.outs))] 28 | 29 | gensyntax = rule( 30 | implementation = _gensyntax_impl, 31 | attrs = { 32 | "yy": attr.label( 33 | allow_single_file = True, 34 | default = "syntaxis.y" 35 | ), 36 | "outs": attr.output_list( ), 37 | "defines": attr.string_list( 38 | ), 39 | "template": attr.label( 40 | allow_single_file = True, 41 | default = "//vendored/lemon:lempar.c" 42 | ), 43 | "_tool": attr.label( 44 | allow_single_file = True, 45 | default = "//vendored/lemon", 46 | executable = True, 47 | cfg = "host" 48 | ) 49 | } 50 | ) 51 | -------------------------------------------------------------------------------- /src/constants.c: -------------------------------------------------------------------------------- 1 | #include "constants.h" 2 | 3 | /* WARNING WARNING: these #defines must be kept in sync with syntaxis.h */ 4 | #if EXPORT_INTERFACE 5 | #define TK_Unspecified 135 6 | #define TK_Unary_Expr 134 7 | #define TK_Target_List 133 8 | #define TK_Target 132 9 | #define TK_Stmt_List 131 10 | #define TK_Stmt 130 11 | #define TK_Small_Stmt_List 129 12 | #define TK_Slice_Sfx 128 13 | #define TK_Slice_Expr 127 14 | #define TK_Return_Expr 126 15 | #define TK_Paren_Expr 125 16 | #define TK_Primary_Expr 124 17 | #define TK_Param_Star2 123 18 | #define TK_Param_Star 122 19 | #define TK_Param_Named 121 20 | #define TK_Param_List 120 21 | #define TK_Node_List 119 22 | #define TK_Loop_Vars 118 23 | #define TK_Load_Stmt 117 24 | #define TK_List_Expr 116 25 | #define TK_List_Comp 115 26 | #define TK_Lambda_Expr 114 27 | #define TK_Indent_Block 113 28 | #define TK_If_Stmt 112 29 | #define TK_If_Expr 111 30 | #define TK_For_Stmt 110 31 | #define TK_Expr_List 109 32 | #define TK_Expr 108 33 | #define TK_Dot_Sfx 107 34 | #define TK_Dot_Expr 106 35 | #define TK_Dict_Expr 105 36 | #define TK_Dict_Entry_List 104 37 | #define TK_Dict_Entry 103 38 | #define TK_Dict_Comp 102 39 | #define TK_Def_Stmt 101 40 | #define TK_Def_Compound 100 41 | #define TK_Comp_Clause 99 42 | #define TK_Call_Sfx 98 43 | #define TK_Call_Expr 97 44 | #define TK_Package 96 45 | #define TK_Bin_Expr 95 46 | #define TK_Assign_Stmt 94 47 | #define TK_Attr_Value 93 48 | #define TK_Attr_Name 92 49 | #define TK_Attr 91 50 | #define TK_Arg_Star2 90 51 | #define TK_Arg_Star 89 52 | #define TK_Binding 88 53 | #define TK_Arg_List 87 54 | #define TK_YIELD 86 55 | #define TK_WITH 85 56 | #define TK_WHILE 84 57 | #define TK_VBAR_EQ 83 58 | #define TK_VBAR 82 59 | #define TK_TRY 81 60 | #define TK_TILDE 80 61 | #define TK_STRING 79 62 | #define TK_STAR2 78 63 | #define TK_STAR_EQ 77 64 | #define TK_STAR 76 65 | #define TK_SLASH 75 66 | #define TK_SEMI 74 67 | #define TK_RRANGLE_EQ 73 68 | #define TK_RRANGLE 72 69 | #define TK_RPAREN 71 70 | #define TK_RETURN 70 71 | #define TK_RBRACK 69 72 | #define TK_RBRACE 68 73 | #define TK_RANGLE 67 74 | #define TK_RAISE 66 75 | #define TK_PLUS_EQ 65 76 | #define TK_PLUS 64 77 | #define TK_PCT_EQ 63 78 | #define TK_PCT 62 79 | #define TK_PASS 61 80 | #define TK_OR 60 81 | #define TK_NOT 59 82 | #define TK_NONLOCAL 58 83 | #define TK_NEWLINE 57 84 | #define TK_MINUS_EQ 56 85 | #define TK_MINUS 55 86 | #define TK_LPAREN 54 87 | #define TK_LOAD 53 88 | #define TK_LLANGLE_EQ 52 89 | #define TK_LLANGLE 51 90 | #define TK_LE 50 91 | #define TK_LBRACK 49 92 | #define TK_LBRACE 48 93 | #define TK_LANGLE 47 94 | #define TK_LAMBDA 46 95 | #define TK_IS 45 96 | #define TK_IN 44 97 | #define TK_INT_OCT 43 98 | #define TK_INT_HEX 42 99 | #define TK_INT_DEC 41 100 | #define TK_INT 40 101 | #define TK_IMPORT 39 102 | #define TK_IF 38 103 | #define TK_ID 37 104 | #define TK_GLOBAL 36 105 | #define TK_GE 35 106 | #define TK_FROM 34 107 | #define TK_FOR 33 108 | #define TK_FLOAT 32 109 | #define TK_FLOAT_LIT 31 110 | #define TK_FINALLY 30 111 | #define TK_EXCEPT 29 112 | #define TK_BACKSLASH2 28 113 | #define TK_EQ2 27 114 | #define TK_EQ 26 115 | #define TK_ELSE 25 116 | #define TK_ELIF 24 117 | #define TK_DOT 23 118 | #define TK_SLASH_EQ 22 119 | #define TK_SLASH2_EQ 21 120 | #define TK_SLASH2 20 121 | #define TK_DEL 19 122 | #define TK_DEF 18 123 | #define TK_CONTINUE 17 124 | #define TK_COMMENT 16 125 | #define TK_COMMA 15 126 | #define TK_COLON 14 127 | #define TK_CLASS 13 128 | #define TK_CARET_EQ 12 129 | #define TK_CARET 11 130 | #define TK_BREAK 10 131 | #define TK_BLANK 9 132 | #define TK_BANG_EQ 8 133 | #define TK_BANG 7 134 | #define TK_ASSERT 6 135 | #define TK_AS 5 136 | #define TK_ARROW 4 137 | #define TK_AND 3 138 | #define TK_AMP_EQ 2 139 | #define TK_AMP 1 140 | #endif 141 | -------------------------------------------------------------------------------- /src/sealark_bindings.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | #include "log.h" 9 | #include "utarray.h" 10 | 11 | #include "sealark_bindings.h" 12 | 13 | /* ******************************** */ 14 | /* returns only bindings (TK_Named_Arg) in a new UT_array */ 15 | /* **************************************************************** */ 16 | /* EXPORT struct node_s *sealark_target_bindings(struct node_s *target) */ 17 | /* { */ 18 | /* #if defined (DEBUG_TRACE) || defined(DEBUG_QUERY) */ 19 | /* log_debug("sealark_target_bindings"); */ 20 | /* #endif */ 21 | 22 | /* log_debug("target tid: %d %s", target->tid, TIDNAME(target)); */ 23 | 24 | /* /\* :call-expr[1] => :call-sfx[1] => :arg-list *\/ */ 25 | /* struct node_s *call_sfx = utarray_eltptr(target->subnodes, 1); */ 26 | /* struct node_s *arg_list = utarray_eltptr(call_sfx->subnodes, 1); */ 27 | 28 | /* return arg_list; */ 29 | /* } */ 30 | 31 | /* **************************************************************** */ 32 | EXPORT struct node_s *sealark_bindings_for_target(struct node_s *target) 33 | { 34 | #if defined (DEBUG_TRACE) || defined(DEBUG_QUERY) 35 | log_debug("sealark_bindings_for_target"); 36 | #endif 37 | 38 | /* log_debug("target tid: %d %s", target->tid, TIDNAME(target)); */ 39 | 40 | /* :call-expr[1] => :call-sfx[1] => :arg-list */ 41 | struct node_s *call_sfx = utarray_eltptr(target->subnodes, 1); 42 | struct node_s *arg_list = utarray_eltptr(call_sfx->subnodes, 1); 43 | 44 | return arg_list; 45 | } 46 | 47 | /* **************************************************************** */ 48 | EXPORT struct node_s *sealark_bindings_for_target_for_name 49 | (struct node_s *package, const char *tgt_name) 50 | { 51 | #if defined (DEBUG_TRACE) || defined(DEBUG_QUERY) 52 | log_debug("sealark_bindings_for_target_for_name %s", tgt_name); 53 | #endif 54 | 55 | struct node_s *target = sealark_target_for_name(package, tgt_name); 56 | 57 | /* UT_array *bindings = sealark_bindings_for_target(target); */ 58 | struct node_s *bindings = sealark_bindings_for_target(target); 59 | return bindings; 60 | } 61 | 62 | /* **************************************************************** */ 63 | /* EXPORT UT_array *sealark_bindings_for_target_for_index */ 64 | EXPORT struct node_s *sealark_bindings_for_target_for_index 65 | (struct node_s *package, int i) 66 | { 67 | #if defined (DEBUG_TRACE) || defined(DEBUG_QUERY) 68 | log_debug("sealark_bindings_for_target_for_index %d", i); 69 | #endif 70 | 71 | struct node_s *target = sealark_target_for_index(package, i); 72 | 73 | /* UT_array *bindings = sealark_bindings_for_target(target); */ 74 | struct node_s *bindings = sealark_bindings_for_target(target); 75 | return bindings; 76 | } 77 | 78 | EXPORT struct node_s *sealark_value_for_binding(struct node_s *binding) 79 | { 80 | #if defined(DEBUG_PATHS) 81 | log_debug("sealark_value_for_binding, tid: %d %s", 82 | binding->tid, token_name[binding->tid][0]); 83 | #endif 84 | #if defined(DEBUG_BINDINGS) 85 | sealark_debug_log_ast_outline(binding, 0); 86 | #endif 87 | /* :binding > :id, :eq, (:list-expr | :string | ...) */ 88 | struct node_s *valnode = utarray_eltptr(binding->subnodes, 2); 89 | return valnode; 90 | } 91 | 92 | /* ******************************** */ 93 | EXPORT struct node_s *sealark_target_binding_for_key(struct node_s *call_expr, const char *key) 94 | { 95 | #if defined(DEBUG_BINDINGS) 96 | log_debug("sealark_target_binding_for_key: %s", key); 97 | #endif 98 | 99 | assert(call_expr->tid == TK_Call_Expr); 100 | 101 | struct node_s *call_sfx = utarray_eltptr(call_expr->subnodes, 1); 102 | struct node_s *arg_list = utarray_eltptr(call_sfx->subnodes, 1); 103 | 104 | struct node_s *id; 105 | int key_len = strlen(key); 106 | struct node_s *arg_node = NULL; 107 | int i = 0; 108 | 109 | while((arg_node=(struct node_s*)utarray_next(arg_list->subnodes, 110 | arg_node))) { 111 | #if defined(DEBUG_UTARRAYS) 112 | log_debug(" LOOP arg_list[%d] tid: %d %s", i++, arg_node->tid, 113 | token_name[arg_node->tid][0]); 114 | #endif 115 | if (arg_node->tid == TK_Binding) { // skip TK_COMMA nodes 116 | id = utarray_eltptr(arg_node->subnodes, 0); 117 | 118 | #if defined(DEBUG_UTARRAYS) 119 | log_debug("testing id[%d]: %d %s", i, id->tid, id->s); 120 | #endif 121 | if ((strncmp(id->s, key, key_len) == 0) 122 | && strlen(id->s) == key_len ){ 123 | 124 | #if defined(DEBUG_UTARRAYS) 125 | log_debug("MATCHED key: %s", key); 126 | #endif 127 | return arg_node; 128 | 129 | } 130 | } else { 131 | } 132 | } 133 | #if defined(DEBUG_UTARRAYS) 134 | log_debug("no match: %s", key); 135 | #endif 136 | errno = ENOT_FOUND_BINDING; 137 | return NULL; 138 | } 139 | 140 | /* ******************************** */ 141 | EXPORT struct node_s *sealark_target_binding_for_index(struct node_s *call_expr, int index) 142 | { 143 | #if defined(DEBUG_TRACE) 144 | log_debug("sealark_target_binding_for_index: %d", index); 145 | #endif 146 | 147 | /* sealark_debug_log_ast_outline(call_expr, 0); */ 148 | /* :call-expr[1] > :call-sfx[1] > :arg-list */ 149 | /* then search arg-list children for arg-named/name=str */ 150 | /* :arg-named[0] = :id */ 151 | 152 | struct node_s *call_sfx = utarray_eltptr(call_expr->subnodes, 1); 153 | struct node_s *arg_list = utarray_eltptr(call_sfx->subnodes, 1); 154 | int arg_list_ct = utarray_len(arg_list->subnodes); 155 | int args_item_ct = (arg_list_ct + 1) / 2; 156 | /* log_debug("arg_list_ct: %d; item ct: %d", arg_list_ct, args_item_ct); */ 157 | 158 | /* reverse indexing */ 159 | if (index < 0) { 160 | if (abs(index) > args_item_ct) { 161 | log_error("abs(%d) > args_item_ct", index, args_item_ct); 162 | errno = 3; 163 | return NULL; 164 | } else { 165 | index = args_item_ct + index; 166 | // do we need to recur? 167 | /* return sealark_target_binding_for_index(call_expr, index); */ 168 | } 169 | } 170 | 171 | if (index > args_item_ct-1) { 172 | log_error("index > target count"); 173 | errno = EINDEX_TOO_BIG; 174 | return NULL; 175 | } 176 | 177 | #if defined(DEBUG_UTARRAYS) 178 | log_debug("SEARCHING arg_list %d %s, child ct: %d, item ct: %d", 179 | arg_list->tid, 180 | token_name[arg_list->tid][0], 181 | arg_list_ct, args_item_ct); 182 | #endif 183 | 184 | /* struct node_s *id; */ 185 | struct node_s *arg_node = NULL; 186 | 187 | /* for target nodes, only bindings (attrs) are allowed in arglist, 188 | so no need to account for non-attribute args 189 | */ 190 | int binding_ct = 0; 191 | while((arg_node=(struct node_s*)utarray_next(arg_list->subnodes, 192 | arg_node))) { 193 | #if defined(DEBUG_UTARRAYS) 194 | log_debug(" LOOP arg_list[%d] tid: %d %s", 195 | binding_ct, arg_node->tid, 196 | token_name[arg_node->tid][0]); 197 | #endif 198 | if (arg_node->tid == TK_Binding) { // skip TK_COMMA nodes 199 | if (binding_ct == index) { 200 | #if defined(DEBUG_UTARRAYS) 201 | log_debug("MATCHED index: %d", binding_ct); 202 | #endif 203 | return arg_node; 204 | } 205 | binding_ct++; 206 | } 207 | } 208 | return NULL; 209 | } 210 | 211 | /* ******************************** */ 212 | EXPORT struct node_s *sealark_bindings_binding_for_index(struct node_s *bindings, int index) 213 | { 214 | #if defined(DEBUG_BINDINGS) 215 | log_debug("sealark_bindings_binding_for_index: %d", index); 216 | /* sealark_debug_log_ast_outline(bindings, 0); */ 217 | #endif 218 | 219 | assert(bindings->tid == TK_Arg_List); 220 | 221 | #if defined(DEBUG_UTARRAYS) 222 | log_debug("SEARCHING bindings %d %s, child ct: %d", 223 | bindings->tid, 224 | token_name[bindings->tid][0], 225 | utarray_len(bindings->subnodes)); 226 | #endif 227 | struct node_s *binding_node = NULL; 228 | 229 | /* reverse indexing */ 230 | int list_ct = utarray_len(bindings->subnodes); 231 | int item_ct = (list_ct + 1) / 2; 232 | if (index < 0) { 233 | if (abs(index) > item_ct) { 234 | log_error("abs(%d) > item_ct", index, item_ct); 235 | errno = 3; 236 | return NULL; 237 | } else { 238 | index = item_ct + index; 239 | log_debug("recurring..."); 240 | return sealark_bindings_binding_for_index(bindings, index); 241 | } 242 | } 243 | 244 | if (index > item_ct-1) { 245 | log_error("index > target count"); 246 | errno = 2; /* FIXME */ 247 | return NULL; 248 | } 249 | 250 | /* for target nodes, only bindings (attrs) are allowed in arglist, 251 | so no need to account for non-attribute args 252 | */ 253 | int binding_ct = 0; 254 | while((binding_node=(struct node_s*)utarray_next(bindings->subnodes, 255 | binding_node))) { 256 | #if defined(DEBUG_UTARRAYS) 257 | log_debug(" LOOP bindings[%d] tid: %d %s", 258 | binding_ct, binding_node->tid, 259 | token_name[binding_node->tid][0]); 260 | #endif 261 | if (binding_node->tid == TK_Binding) { // skip TK_COMMA nodes 262 | if (binding_ct == index) { 263 | #if defined(DEBUG_UTARRAYS) 264 | log_debug("MATCHED index: %d", binding_ct); 265 | #endif 266 | return binding_node; 267 | } 268 | binding_ct++; 269 | } 270 | } 271 | return NULL; 272 | } 273 | 274 | /* ******************************** */ 275 | EXPORT int sealark_binding_index_for_key(struct node_s *bindings, 276 | const char *key) 277 | { 278 | #if defined(DEBUG_BINDINGS) 279 | log_debug("sealark_binding_index_for_key: %s", key); 280 | #endif 281 | 282 | assert(bindings->tid == TK_Arg_List); 283 | 284 | int key_len = strlen(key); 285 | 286 | struct node_s *bkey; 287 | struct node_s *bnode = NULL; 288 | int i = 0; 289 | 290 | while((bnode=(struct node_s*)utarray_next(bindings->subnodes, 291 | bnode))) { 292 | #if defined(DEBUG_UTARRAYS) 293 | log_debug(" LOOP bindings[%d] tid: %d %s", 294 | i, bnode->tid, 295 | token_name[bnode->tid][0]); 296 | #endif 297 | if (bnode->tid == TK_Binding) { 298 | bkey = utarray_eltptr(bnode->subnodes, 0); 299 | if ( (strncmp(bkey->s, key, key_len) == 0) 300 | && strlen(bkey->s) == key_len ) { 301 | #if defined(DEBUG_UTARRAYS) 302 | log_debug("MATCHED key: %s", key); 303 | #endif 304 | return i / 2; 305 | } 306 | } 307 | i++; 308 | } 309 | return -1; 310 | } 311 | -------------------------------------------------------------------------------- /src/sealark_ctors.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | #include "log.h" 9 | #include "utarray.h" 10 | 11 | #include "sealark_ctors.h" 12 | 13 | struct node_s *sealark_make_binding_bool(char *key, bool val) 14 | { 15 | } 16 | 17 | EXPORT struct node_s *sealark_make_binding_int(const char *key, int val) 18 | { 19 | struct node_s *binding = sealark_new_node(TK_Binding, with_subnodes); 20 | struct node_s *keynode = sealark_new_node(TK_ID, without_subnodes); 21 | int len = strlen(key); 22 | keynode->s = calloc(len, sizeof(char)); 23 | strncpy(keynode->s, key, len+1); 24 | utarray_push_back(binding->subnodes, keynode); 25 | 26 | struct node_s *eq = sealark_new_node(TK_EQ, without_subnodes); 27 | utarray_push_back(binding->subnodes, eq); 28 | 29 | struct node_s *valnd = sealark_new_node(TK_INT, without_subnodes); 30 | char buf[32]; 31 | snprintf(buf, 32, "%d", val); 32 | valnd->s = calloc(strlen(buf)+1, sizeof(char)); 33 | snprintf(valnd->s, strlen(buf)+1, buf); 34 | 35 | utarray_push_back(binding->subnodes, valnd); 36 | 37 | return binding; 38 | } 39 | 40 | struct node_s *sealark_make_binding_int_list(char *key, UT_array *vals) 41 | { 42 | } 43 | 44 | struct node_s *sealark_make_binding_string(char *key, char *val) 45 | { 46 | } 47 | 48 | struct node_s *sealark_make_binding_string_list(char *key, UT_array *vals) 49 | { 50 | } 51 | 52 | struct node_s *sealark_make_binding_sym(char *key, char *val) 53 | { 54 | } 55 | 56 | -------------------------------------------------------------------------------- /src/sealark_debug.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #include "log.h" 5 | #include "utarray.h" 6 | #include "utstring.h" 7 | 8 | #include "sealark_debug.h" 9 | 10 | void print_stacktrace(void) 11 | { 12 | void* callstack[128]; 13 | int i, frames = backtrace(callstack, 128); 14 | char** strs = backtrace_symbols(callstack, frames); 15 | for (i = 0; i < frames; ++i) { 16 | printf("%s\n", strs[i]); 17 | } 18 | free(strs); 19 | } 20 | 21 | /* ******************************** */ 22 | //FIXME: consolidate debug_print and debug_display to write to single port? 23 | /* recursively print outline to string */ 24 | EXPORT UT_string *sealark_debug_display_ast_outline(struct node_s *node, int level) 25 | { 26 | #if defined(DEBUG_SERIALIZER) 27 | log_debug("sealark_debug_display_ast_outline"); 28 | #endif 29 | 30 | UT_string *buf; 31 | utstring_new(buf); 32 | 33 | _debug_display_ast_outline(node, buf, level); 34 | 35 | return buf; 36 | } 37 | 38 | LOCAL void _debug_display_ast_outline(struct node_s *node, 39 | UT_string *buf, 40 | int level) 41 | { 42 | #if defined(DEBUG_SERIALIZER) 43 | log_debug("_debug_display_ast_outline"); 44 | #endif 45 | 46 | switch(node->tid) { 47 | case TK_STRING: { 48 | char *br = SEALARK_STRTYPE(node->qtype); 49 | char *q = sealark_quote_type(node); 50 | /* utstring_printf(buf, "%s%s%s%s", */ 51 | /* br, q, node->s, q); */ 52 | 53 | // [idx: %d]", 54 | utstring_printf(buf, "%*.s%d: %s[%d] @%d:%d %s%s%s%s\n", 55 | 2*level, " ", level, TIDNAME(node), node->tid, 56 | node->line, node->col, 57 | br, q, node->s, q); 58 | /* node->index); */ 59 | } 60 | break; 61 | case TK_INT: 62 | utstring_printf(buf, "%*.s%d: %s[%d] @%d:%d %s\n", 63 | 2*level, " ", level, TIDNAME(node), node->tid, 64 | node->line, node->col, node->s); 65 | break; 66 | case TK_ID: 67 | utstring_printf(buf, "%*.s%d: %s[%d] @%d:%d %s\n", 68 | 2*level, " ", level, TIDNAME(node), node->tid, 69 | node->line, node->col, node->s); 70 | break; 71 | default: 72 | utstring_printf(buf, "%*.s%d: %s[%d] @%d:%d\n", 73 | 2*level, " ", level, TIDNAME(node), node->tid, 74 | node->line, node->col); 75 | if (node->comments) { 76 | struct node_s *subnode = NULL; 77 | while((subnode=(struct node_s*)utarray_next(node->comments, 78 | subnode))) { 79 | _debug_display_ast_outline(subnode, buf, level+1); 80 | } 81 | } 82 | if (node->subnodes) { 83 | struct node_s *subnode = NULL; 84 | while((subnode=(struct node_s*)utarray_next(node->subnodes, 85 | subnode))) { 86 | _debug_display_ast_outline(subnode, buf, level+1); 87 | } 88 | } 89 | } 90 | } 91 | 92 | /* ******************************** */ 93 | /* recursively print outline to stdout */ 94 | EXPORT void sealark_debug_log_ast_outline(struct node_s *node, int level) 95 | { 96 | #if defined(DEBUG_SERIALIZER) 97 | log_debug("sealark_debug_log_ast_outline %p", node); 98 | #endif 99 | 100 | /* print_stacktrace(); */ 101 | 102 | switch(node->tid) { 103 | case TK_STRING: { 104 | char *br = SEALARK_STRTYPE(node->qtype); 105 | char *q = sealark_quote_type(node); 106 | /* utstring_printf(buffer, "%s%s%s%s", */ 107 | /* br, q, node->s, q); */ 108 | 109 | // [idx: %d]", 110 | log_debug("%*.s%d: %s[%d] @%d:%d %s%s%s%s", 111 | 2*level, " ", level, TIDNAME(node), node->tid, 112 | node->line, node->col, 113 | br, q, node->s, q); 114 | /* node->index); */ 115 | } 116 | break; 117 | case TK_INT: 118 | log_debug("%*.s%d: %s[%d] @%d:%d %s", 119 | 2*level, " ", level, TIDNAME(node), node->tid, 120 | node->line, node->col, node->s); 121 | break; 122 | case TK_ID: 123 | log_debug("%*.s%d: %s[%d] @%d:%d %s", 124 | 2*level, " ", level, TIDNAME(node), node->tid, 125 | node->line, node->col, node->s); 126 | break; 127 | default: 128 | log_debug("%*.s%d: %s[%d] @%d:%d", 129 | 2*level, " ", level, TIDNAME(node), node->tid, 130 | node->line, node->col); 131 | if (node->subnodes) { 132 | struct node_s *subnode = NULL; 133 | while((subnode=(struct node_s*)utarray_next(node->subnodes, 134 | subnode))) { 135 | sealark_debug_log_ast_outline(subnode, level+1); 136 | } 137 | } 138 | } 139 | } 140 | 141 | EXPORT void sealark_debug_print_node_starlark(struct node_s *node, 142 | bool crush) 143 | { 144 | UT_string *buf; 145 | char *str; 146 | utstring_new(buf); 147 | sealark_node_to_starlark(node, buf); 148 | if (crush) 149 | str = sealark_crush_string(buf); 150 | else 151 | str = utstring_body(buf); 152 | log_debug("%s", str); 153 | if (crush) free(str); 154 | utstring_free(buf); 155 | } 156 | 157 | EXPORT void sealark_dump_node(struct node_s *node) 158 | { 159 | log_debug("dump_node: %p", node); 160 | log_debug("%s[%d] %c (%d:%d)", 161 | token_name[node->tid][0], 162 | node->tid, 163 | /* node->tid == TK_STRING? node->q: ' ', */ 164 | (node->qtype && SQUOTE)? '\'' 165 | /* : (node->qtype == DQUOTE)? '"' */ 166 | : '"', 167 | node->line, node->col); 168 | switch (node->tid) { 169 | case TK_COMMENT: log_debug("\tstarttok: %s", node->s); break; 170 | case TK_ID: log_debug("\tstarttok: %s", node->s); break; 171 | case TK_INT: log_debug("\tstarttok: %s", node->s); break; 172 | case TK_STRING: log_debug("\tstarttok: %s", node->s); break; 173 | } 174 | if (node->comments) { 175 | if (utarray_len(node->comments) > 0) { 176 | log_debug("\tdumping comments"); 177 | dump_nodes(node->comments); 178 | log_debug("\tend dumping comments"); 179 | } 180 | } 181 | if (node->subnodes) dump_nodes(node->subnodes); 182 | log_debug("/dump_node"); 183 | } 184 | 185 | EXPORT void dump_nodes(UT_array *nodes) 186 | { 187 | log_debug("dump_nodes: %p, ct: %d", nodes, utarray_len(nodes)); 188 | 189 | struct node_s *node=NULL; 190 | char *q; 191 | while( (node=(struct node_s*)utarray_next(nodes, node))) { 192 | /* log_debug("qtype: %#x", node->qtype); */ 193 | /* node->tid, */ 194 | /* token_name[node->tid][0]); */ 195 | if (node->qtype & SQUOTE) { 196 | if (node->qtype & TRIPLE) { 197 | q = "'''"; 198 | } else { 199 | q = "'"; 200 | } 201 | } else { 202 | if ( !(node->qtype & SQUOTE) ) { 203 | if (node->qtype & TRIPLE) { 204 | q = "\"\"\""; 205 | } else { 206 | q = "\""; 207 | } 208 | } else { 209 | q = ""; 210 | } 211 | } 212 | 213 | log_debug("%s[%d] %s %s (%d:%d)", 214 | token_name[node->tid][0], 215 | node->tid, 216 | 217 | ((node->qtype & BINARY_STR) && 218 | (node->qtype & RAW_STR))? "br" 219 | : (node->qtype & BINARY_STR)? "b" 220 | : (node->qtype & RAW_STR)? "r" 221 | : "", 222 | 223 | q, 224 | node->line, node->col); 225 | 226 | /* if (node->s) log_debug("\tstarttok: :]%s[:", node->s); */ 227 | switch (node->tid) { 228 | case TK_COMMENT: log_debug("\tstarttok: %s", node->s); break; 229 | case TK_ID: log_debug("\tstarttok: :]%s[:", node->s); break; 230 | case TK_INT: log_debug("\tstarttok: :]%s[:", node->s); break; 231 | case TK_STRING: log_debug("\tstarttok: :]%s[:", node->s); break; 232 | /* case TK_Call_Sfx: log_debug("\tstarttok: %s", node->s); break; */ 233 | case TK_Dot_Sfx: log_debug("\tstarttok: %s", node->s); break; 234 | } 235 | if (node->comments) { 236 | if (utarray_len(node->comments) > 0) { 237 | log_debug(" dumping comments"); 238 | dump_nodes(node->comments); 239 | log_debug(" /dumping comments"); 240 | } 241 | } 242 | if (node->subnodes) { 243 | if (utarray_len(node->subnodes) > 0) { 244 | log_debug(" subnodes:"); 245 | dump_nodes(node->subnodes); 246 | log_debug(" /subnodes %s[%d]", 247 | token_name[node->tid][0], node->tid); 248 | } 249 | } 250 | } 251 | log_debug("/dump_nodes"); 252 | } 253 | -------------------------------------------------------------------------------- /src/sealark_dictionaries.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | #include "log.h" 9 | #include "utarray.h" 10 | 11 | #include "sealark_dictionaries.h" 12 | 13 | /* 14 | 4: TK_Dict_Expr[105] @11:12 15 | 5: TK_LBRACE[48] @11:12 16 | 5: TK_Dict_Entry_List[104] @12:8 17 | 6: TK_Dict_Entry[103] @12:8 18 | 7: TK_STRING[79] @12:8 "ckey1" 19 | 7: TK_COLON[14] @12:15 20 | 7: TK_STRING[79] @12:17 "cval1" 21 | 6: TK_COMMA[15] @12:24 22 | 6: TK_Dict_Entry[103] @13:8 23 | 7: TK_STRING[79] @13:8 "ckey2" 24 | 7: TK_COLON[14] @13:15 25 | 7: TK_INT[79] @13:17 7 26 | 6: TK_COMMA[15] @13:24 27 | ...etc... 28 | 5: TK_RBRACE[68] @15:4 29 | */ 30 | 31 | /* 32 | */ 33 | EXPORT int sealark_dict_expr_length(struct node_s *dict_expr) 34 | { 35 | #if defined (DEBUG_TRACE) || defined(DEBUG_VECTORS) 36 | log_debug("sealark_dict_expr_length"); 37 | #endif 38 | 39 | struct node_s *dentries = utarray_eltptr(dict_expr->subnodes, 1); 40 | int ct = utarray_len(dentries->subnodes); 41 | ct = (ct + 1) / 2; 42 | return ct; 43 | } 44 | 45 | /* 46 | */ 47 | EXPORT struct node_s *sealark_dict_entry_for_int(struct node_s *dict_expr, 48 | int index) 49 | { 50 | 51 | #if defined (DEBUG_TRACE) || defined(DEBUG_VECTORS) 52 | log_debug("sealark_dict_entry_for_int: %d", index); 53 | #endif 54 | 55 | assert(dict_expr->tid == TK_Dict_Expr); 56 | 57 | struct node_s *entry_list = utarray_eltptr(dict_expr->subnodes, 1); 58 | 59 | int list_ct = utarray_len(entry_list->subnodes); 60 | int item_ct = (list_ct + 1) / 2; 61 | 62 | /* reverse indexing */ 63 | if (index < 0) { 64 | if (abs(index) > item_ct) { 65 | log_error("abs(%d) > item_ct", index, item_ct); 66 | errno = EINDEX_OUT_OF_BOUNDS; 67 | return NULL; 68 | } else { 69 | index = item_ct + index; 70 | /* log_debug("recurring..."); */ 71 | /* return sealark_dict_entry_for_int(dict_expr, index); */ 72 | } 73 | } 74 | 75 | if (index > item_ct-1) { 76 | log_error("index > target count"); 77 | errno = EINDEX_OUT_OF_BOUNDS; 78 | return NULL; 79 | } 80 | 81 | /* struct node_s *entry_list = utarray_eltptr(dict_expr->subnodes, 1); */ 82 | /* item_ct = utarray_len(entry_list->subnodes); */ 83 | /* if (index*2 > item_ct) { */ 84 | /* log_error("index out of bounds: %d", index); */ 85 | /* return NULL; */ 86 | /* } */ 87 | 88 | //FIXME: support negative index 89 | 90 | return utarray_eltptr(entry_list->subnodes, index*2); 91 | 92 | log_error("UNEXPECTED"); 93 | exit(EXIT_FAILURE); 94 | } 95 | 96 | EXPORT struct node_s *sealark_dict_entry_for_string_key(struct node_s *dict_expr, 97 | const char *key) 98 | { 99 | #if defined (DEBUG_TRACE) || defined(DEBUG_VECTORS) 100 | log_debug("sealark_dict_entry_for_string_key: %s", key); 101 | #endif 102 | 103 | assert(dict_expr->tid == TK_Dict_Expr); 104 | 105 | struct node_s *entry_list = utarray_eltptr(dict_expr->subnodes, 1); 106 | 107 | int key_len = strlen(key); 108 | 109 | int list_ct = utarray_len(entry_list->subnodes); 110 | int item_ct = (list_ct + 1) / 2; 111 | 112 | struct node_s *ekey; 113 | struct node_s *sub = NULL; 114 | int i = 0; 115 | while( (sub=(struct node_s*)utarray_next(entry_list->subnodes, sub)) ) { 116 | if (sub->tid == TK_Dict_Entry) { 117 | ekey = utarray_eltptr(sub->subnodes, 0); 118 | 119 | if (ekey->tid == TK_STRING) { 120 | if ( (strncmp(ekey->s, key, key_len) == 0) 121 | && (strlen(ekey->s) == key_len) ) { 122 | /* match */ 123 | return sub; 124 | } 125 | } 126 | } 127 | i++; 128 | } 129 | errno = ENOT_FOUND; 130 | return NULL; 131 | } 132 | 133 | int sealark_dict_index_for_string_key(struct node_s *dict_expr, 134 | const char *key) 135 | { 136 | #if defined (DEBUG_TRACE) || defined(DEBUG_VECTORS) 137 | log_debug("sealark_dict_index_for_string_key: %s", key); 138 | #endif 139 | 140 | assert(dict_expr->tid == TK_Dict_Expr); 141 | 142 | struct node_s *entry_list = utarray_eltptr(dict_expr->subnodes, 1); 143 | 144 | int key_len = strlen(key); 145 | 146 | int list_ct = utarray_len(entry_list->subnodes); 147 | int item_ct = (list_ct + 1) / 2; 148 | 149 | struct node_s *ekey; 150 | struct node_s *sub = NULL; 151 | int i = 0; 152 | while( (sub=(struct node_s*)utarray_next(entry_list->subnodes, sub)) ) { 153 | if (sub->tid == TK_Dict_Entry) { 154 | ekey = utarray_eltptr(sub->subnodes, 0); 155 | 156 | if (ekey->tid == TK_STRING) { 157 | if ( (strncmp(ekey->s, key, key_len) == 0) 158 | && (strlen(ekey->s) == key_len) ) { 159 | /* match */ 160 | return i; 161 | } 162 | } 163 | } 164 | i++; 165 | } 166 | 167 | log_error("UNEXPECTED"); 168 | exit(EXIT_FAILURE); 169 | } 170 | 171 | /* **************************************************************** */ 172 | /* NB: returns list of mapentries (idx .item) */ 173 | EXPORT UT_array *sealark_dict_items_for_string(struct node_s *dexpr, 174 | const char *selector) 175 | { 176 | #if defined(DEBUG_TRACE) 177 | log_debug("sunlark_dict_items_for_string: %s", selector); 178 | #endif 179 | log_debug("dexpr tid: %d %s", dexpr->tid, TIDNAME(dexpr)); 180 | assert(dexpr->tid == TK_Dict_Expr); 181 | 182 | int selector_len = strlen(selector); 183 | 184 | /* struct node_s *new_list = sealark_new_dict_expr(); */ 185 | /* assert(new_list->tid == TK_Dict_Expr); */ 186 | /* new_list->index = 1; */ 187 | /* struct node_s *new_items = utarray_eltptr(new_list->subnodes, 1); */ 188 | 189 | /* UT_array *nodemap; */ 190 | /* utarray_new(nodemap, &mapentry_icd); // client deletes */ 191 | /* struct mapentry_s *mapentry; */ 192 | 193 | UT_array *items; 194 | utarray_new(items, &node_icd); 195 | /* struct node_s *comma; */ 196 | 197 | struct node_s *dentry_list = utarray_eltptr(dexpr->subnodes, 1); 198 | int item_ct = utarray_len(dentry_list->subnodes); 199 | 200 | struct node_s *sub = NULL; 201 | int i = 0; 202 | while( (sub=(struct node_s*)utarray_next(dentry_list->subnodes, sub)) ) { 203 | if (sub->tid == TK_ID) i++; 204 | if (sub->tid == TK_STRING) { 205 | if ((strncmp(sub->s, selector, selector_len) == 0) 206 | && strlen(sub->s) == selector_len ){ 207 | utarray_push_back(items, sub); 208 | 209 | /* mapentry = calloc(1, sizeof(struct mapentry_s)); // client deletes */ 210 | /* mapentry->index = i; */ 211 | /* mapentry->node = sub; */ 212 | /* utarray_push_back(nodemap, mapentry); */ 213 | /* free(mapentry); // push_back copies, so we can free? */ 214 | /* fixme: omit trailing comma */ 215 | /* comma = sealark_new_node(TK_COMMA, without_subnodes); */ 216 | /* utarray_push_back(new_items->subnodes, comma); */ 217 | } 218 | i++; 219 | } 220 | } 221 | return items; 222 | } 223 | 224 | /* **************************************************************** */ 225 | EXPORT void sealark_update_dict_items(UT_array *items, 226 | const char *newval) 227 | { 228 | #if defined(DEBUG_TRACE) 229 | log_debug("sealark_update_dict_items: %s", newval); 230 | #endif 231 | 232 | log_debug("found %d items", utarray_len(items)); 233 | 234 | int newval_len = strlen(newval); 235 | 236 | int i = 0; 237 | struct node_s *sub = NULL; 238 | while( (sub=(struct node_s*)utarray_next(items, sub)) ) { 239 | free(sub->s); 240 | sub->s = calloc(newval_len + 1, sizeof(char)); 241 | strncpy(sub->s, newval, newval_len + 1); 242 | } 243 | 244 | /* struct mapentry_s *mentry = NULL; */ 245 | /* int i = 0; */ 246 | /* while( (mentry=(struct mapentry_s*)utarray_next(items, mentry)) ) { */ 247 | /* /\* assert(mentry->node->tid == TK_STRING); *\/ */ 248 | /* if (mentry->node->tid == TK_ID) { */ 249 | /* } */ 250 | /* if (mentry->node->tid == TK_STRING) { */ 251 | /* free(mentry->node->s); */ 252 | /* mentry->node->s = calloc(newval_len + 1, sizeof(char)); */ 253 | /* strncpy(mentry->node->s, newval, newval_len + 1); */ 254 | /* } */ 255 | /* } */ 256 | } 257 | 258 | /* **************************************************************** */ 259 | EXPORT struct node_s *sealark_dexpr_rm_entry_for_int(struct node_s *dexpr, 260 | int index) 261 | { 262 | #if defined(DEBUG_TRACE) 263 | log_debug("sealark_dexpr_rm_entry_for_int: %d", index); 264 | #endif 265 | 266 | assert(dexpr->tid == TK_Dict_Expr); 267 | 268 | struct node_s *dentries = utarray_eltptr(dexpr->subnodes, 1); 269 | assert(dentries->tid == TK_Dict_Entry_List); 270 | 271 | int subnode_ct = utarray_len(dentries->subnodes); 272 | /* each item except the last followed by comma */ 273 | int item_ct = (subnode_ct + 1) / 2; 274 | 275 | /* reverse indexing */ 276 | if (index < 0) { 277 | if (abs(index) > item_ct) { 278 | log_error("abs(%d) > item_ct", index, item_ct); 279 | errno = EINDEX_OUT_OF_BOUNDS; 280 | return NULL; 281 | } else { 282 | index = item_ct + index; 283 | } 284 | } 285 | 286 | if (index > item_ct-1) { 287 | log_error("desired index %d > item count %d", index, item_ct); 288 | errno = EINDEX_OUT_OF_BOUNDS; 289 | return NULL; 290 | } 291 | int n; 292 | if (index == item_ct - 1) 293 | n = item_ct - 2; // back up one to prevent trailing comma 294 | else 295 | n = 2; 296 | 297 | utarray_erase(dentries->subnodes, index, n); 298 | 299 | return dexpr; 300 | } 301 | 302 | /* **************************************************************** */ 303 | EXPORT struct node_s *sealark_dexpr_rm_entry_for_string(struct node_s *dexpr, 304 | const char* s) 305 | { 306 | #if defined(DEBUG_TRACE) 307 | log_debug("sealark_dexpr_rm_entry_for_string: %s", s); 308 | #endif 309 | 310 | assert(dexpr->tid == TK_Dict_Expr); 311 | 312 | struct node_s *dentries = utarray_eltptr(dexpr->subnodes, 1); 313 | assert(dentries->tid == TK_Dict_Entry_List); 314 | 315 | int subnode_ct = utarray_len(dentries->subnodes); 316 | /* each item except the last followed by comma */ 317 | int item_ct = (subnode_ct + 1) / 2; 318 | 319 | int index = sealark_dict_index_for_string_key(dexpr, s); 320 | int n; 321 | if (index == item_ct - 1) 322 | n = item_ct - 2; // back up one to prevent trailing comma 323 | else 324 | n = 2; 325 | 326 | utarray_erase(dentries->subnodes, index, n); 327 | 328 | return dexpr; 329 | } 330 | 331 | -------------------------------------------------------------------------------- /src/sealark_errors.c: -------------------------------------------------------------------------------- 1 | 2 | #if EXPORT_INTERFACE 3 | #define ESUNLARK_INVALID_ARG -1 4 | #define ESUNLARK_ARG_TYPE_ERR -2 5 | #define ESUNLARK_LOCN_ARG_ERR -3 6 | #define EINDEX_TOO_BIG -4 7 | #define EINVALID_ARG -5 8 | #define EINVALID_ARG_LOAD -6 9 | #define ENOT_FOUND -7 10 | #define ENOT_FOUND_BINDING -8 11 | #define ETOO_MANY_ARGS -9 12 | #define ETOO_MANY_ARGS_BINDINGS -10 13 | #define EMISSING_ARG_SELECTOR -11 14 | #define EMISSING_ARG_BINDING -12 15 | #define ENOT_IMPLEMENTED -13 16 | #define EINVALID_INDEX -14 17 | #define EUNKNOWN_KW -15 18 | #define EINVALID_VECINDEX -16 19 | #define ENULL_BINDING_VAL -17 20 | #define EINDEX_OUT_OF_BOUNDS -18 21 | #define EINVALID_UPDATE -19 22 | #define EINDEX_TYPE_ERR -20 23 | #define EINVALID_REMOVE -21 24 | #define EINVALID_INT_INDEX -22 25 | #define EUNEXPECTED_STATE -23 26 | #define EKW_NOT_NBR -24 27 | #define ENOT_A_KW -25 28 | #define ESPLICE_ARG -26 29 | #define ESPLICE_BINDING_ARG -27 30 | #define EUNKNOWN_C_OBJECT_TYPE -28 31 | #define EMISSING_GET_SELECTOR -29 32 | #define EINVALID_GET_SELECTOR -30 33 | #define EINVALID_ACTION -31 34 | #define EINVALID_SERIALIZE_AST -32 35 | #define EINVALID_SERIALIZE_STARLARK -33 36 | #define ESPLICE_ERR -34 37 | #define EINVALID_LOAD_ARG -35 38 | #define EINVALID_LOAD_ARG_VAL -36 39 | #define EINVALID_LOAD_CTOR_ARGLIST -37 40 | #define EINVALID_LOAD_CTOR_KEY -38 41 | #define EINVALID_LOAD_CTOR_ARGS -39 42 | #define EINVALID_LOAD_CTOR_ATTRS -40 43 | #define EINVALID_LOAD_CTOR_ATTR -41 44 | #define EINVALID_LOAD_NEWVAL -42 45 | #define EINVALID_LOAD_SELECTOR -43 46 | #define ESPLICE_LOADSTMT_ARG -44 47 | #define ESPLICE_LOADSTMT_ATTR -45 48 | #define EINVALID_SET_ATTR_NEWVAL -46 49 | #define EMISSING_ARG_TARGET -47 50 | 51 | #endif 52 | 53 | int e; 54 | -------------------------------------------------------------------------------- /src/sealark_mutators.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | #include "log.h" 9 | #include "utarray.h" 10 | 11 | #include "sealark_mutators.h" 12 | 13 | /* **************** */ 14 | EXPORT struct node_s *sealark_set_int(struct node_s *node, 15 | const int newint) 16 | { 17 | #if defined(DEBUG_TRACE) || defined(DEBUG_MUTATE) 18 | log_debug("sealark_set_int: %d", newint); 19 | #endif 20 | 21 | assert(node->tid == TK_INT); 22 | 23 | /* int d = s7_integer(newint); */ 24 | char buf[128]; 25 | snprintf(buf, 128, "%d", newint); 26 | int len = strlen(buf); 27 | /* log_debug("new val: %d", newint); */ 28 | node->tid = TK_INT; 29 | node->s = calloc(len, sizeof(char)); 30 | strncpy(node->s, buf, len); 31 | return node; 32 | } 33 | 34 | /* **************** */ 35 | /* string flags in sealark_nodes.c */ 36 | EXPORT struct node_s *sealark_set_string(struct node_s *node, 37 | int qtype, 38 | const char *newstr) 39 | { 40 | #if defined(DEBUG_TRACE) || defined(DEBUG_MUTATE) 41 | log_debug("sealark_set_string: %s", newstr); 42 | #endif 43 | 44 | if (node->tid != TK_STRING) { 45 | if (node->subnodes) { 46 | utarray_free(node->subnodes); 47 | node->subnodes = NULL; 48 | } 49 | } 50 | node->tid = TK_STRING; 51 | node->qtype = qtype; //(qmark | qqq | qtype); 52 | /* log_debug("qtype: %#04x", node->qtype); */ 53 | 54 | int len = strlen(newstr); 55 | node->s = calloc(len, sizeof(char)); 56 | strncpy(node->s, newstr, len); 57 | return node; 58 | } 59 | 60 | EXPORT struct node_s *sealark_set_string_c_object(struct node_s *node, 61 | struct node_s *newstr) 62 | { 63 | #if defined(DEBUG_TRACE) || defined(DEBUG_MUTATE) 64 | log_debug("sealark_set_string_c_object"); 65 | #endif 66 | 67 | if (node->tid != TK_STRING) { 68 | if (node->subnodes) { 69 | utarray_free(node->subnodes); 70 | node->subnodes = NULL; 71 | } 72 | } 73 | node->tid = TK_STRING; 74 | node->qtype = newstr->qtype; 75 | /* log_debug("qtype: %#04x", node->qtype); */ 76 | 77 | int len = strlen(newstr->s); 78 | node->s = calloc(len, sizeof(char)); 79 | strncpy(node->s, newstr->s, len); 80 | return node; 81 | } 82 | 83 | /* **************** */ 84 | EXPORT struct node_s *sealark_set_symbol(struct node_s *node, 85 | const char *newstr) 86 | { 87 | #if defined(DEBUG_TRACE) || defined(DEBUG_MUTATE) 88 | log_debug("sealark_set_symbol: %s", newstr); 89 | #endif 90 | 91 | if (node->tid != TK_ID) { 92 | if (node->subnodes) { 93 | utarray_free(node->subnodes); 94 | node->subnodes = NULL; 95 | } 96 | } 97 | node->qtype = 0; 98 | node->tid = TK_ID; 99 | int len = strlen(newstr); 100 | node->s = calloc(len, sizeof(char)); 101 | strncpy(node->s, newstr, len); 102 | return node; 103 | } 104 | -------------------------------------------------------------------------------- /src/sealark_predicators.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | #include "log.h" 7 | 8 | #include "sealark_predicators.h" 9 | 10 | EXPORT bool sealark_is_printable(struct node_s *ast_node) 11 | { 12 | /* log_debug("tid %d printable?", ast_node->tid); */ 13 | for (int i = 0; printable_tokens[i] != 0; i++) { 14 | /* log_debug("tok %d, printable? %d", i, printable_tokens[i]); */ 15 | if (ast_node->tid == printable_tokens[i]) { 16 | return true; 17 | } 18 | } 19 | return false; 20 | } 21 | 22 | EXPORT bool sealark_is_name_attr(struct node_s *node) 23 | { 24 | #ifdef DEBUG_PREDICATES 25 | log_debug("sealark_is_name_attr %d %s", node->tid, TIDNAME(node)); 26 | #endif 27 | 28 | if (node->tid != TK_Binding) return false; 29 | struct node_s *key = utarray_eltptr(node->subnodes, 0); 30 | /* log_debug("keystr: %s", key->s); */ 31 | if ((strncmp(key->s, "name", 4) == 0) && strlen(key->s) == 4) { 32 | return true; 33 | } 34 | return false; 35 | } 36 | 37 | EXPORT bool sealark_call_expr_is_target(struct node_s *call_expr) 38 | { 39 | #ifdef DEBUG_PREDICATES 40 | log_debug("sealark_call_expr_is_target"); 41 | #endif 42 | if (call_expr->tid != TK_Call_Expr) return false; 43 | 44 | // find name attrib 45 | /* :call-expr[1] > :call-sfx[1] > :arg-list[0] */ 46 | /* then search arg-list children for arg-named/name=str */ 47 | /* :arg-named[0] = :id */ 48 | /* struct node_s *stmt_list = utarray_eltptr(call_expr->subnodes, 0); */ 49 | 50 | node_s *binding = sealark_target_binding_for_key(call_expr, "name"); 51 | if (binding) { 52 | return true; 53 | } else 54 | return false; 55 | 56 | } 57 | 58 | /* ******************************** */ 59 | /* matches key and value */ 60 | //FIXME: this is an expressor, not a predicate 61 | /* EXPORT struct node_s *sealark_binding_for_target(struct node_s *call_expr, */ 62 | EXPORT struct node_s *sealark_target_has_binding(struct node_s *call_expr, 63 | const char *key, 64 | const char *val) 65 | { 66 | #if defined(DEBUG_PREDICATORS) 67 | log_debug("sealark_target_has_binding: %s = %s", key, val); 68 | #endif 69 | /* :call-expr[1] > :call-sfx[1] > :arg-list */ 70 | /* then search arg-list children for arg-named/name=str */ 71 | /* :arg-named[0] = :id */ 72 | 73 | struct node_s *call_sfx = utarray_eltptr(call_expr->subnodes, 1); 74 | struct node_s *arg_list = utarray_eltptr(call_sfx->subnodes, 1); 75 | 76 | /* struct node_s *node, *binding; */ 77 | #if defined(DEBUG_UTARRAYS) 78 | log_debug("SEARCHING arg_list %d %s, child ct: %d", 79 | arg_list->tid, 80 | token_name[arg_list->tid][0], 81 | utarray_len(arg_list->subnodes)); 82 | #endif 83 | struct node_s *key_node, *val_node; 84 | int key_len = strlen(key); 85 | int val_len = strlen(val); 86 | 87 | struct node_s *binding_node = NULL; 88 | int i = 0; 89 | 90 | while((binding_node=(struct node_s*)utarray_next(arg_list->subnodes, 91 | binding_node))) { 92 | #if defined(DEBUG_UTARRAYS) 93 | log_debug(" LOOP arg_list[%d] tid: %d %s", i++, binding_node->tid, 94 | token_name[binding_node->tid][0]); 95 | #endif 96 | if (binding_node->tid == TK_Binding) { // skip TK_COMMA nodes 97 | key_node = utarray_eltptr(binding_node->subnodes, 0); 98 | #if defined(DEBUG_UTARRAYS) 99 | log_debug("testing key_node[%d]: %d %s", i, key_node->tid, key_node->s); 100 | #endif 101 | 102 | if ((strncmp(key_node->s, key, key_len) == 0) 103 | && strlen(key_node->s) == key_len ){ 104 | #if defined(DEBUG_UTARRAYS) 105 | log_debug("MATCHED KEY %s", key); 106 | #endif 107 | /* key matches, now test value */ 108 | val_node = utarray_eltptr(binding_node->subnodes, 2); 109 | if (val_node->tid == TK_STRING) { 110 | /* log_debug("\tbinding: %s = %s", key_node->s, val_node->s); */ 111 | 112 | if ( (strncmp(val_node->s, val, val_len) == 0) 113 | && strlen(val_node->s) == val_len ) { 114 | return binding_node; 115 | } 116 | } else { 117 | log_debug("binding val not string: %d %s", 118 | val_node->tid, TIDNAME(val_node)); 119 | } 120 | } 121 | } else { 122 | } 123 | } 124 | return NULL; 125 | } 126 | 127 | /* **************** */ 128 | /* matches key only */ 129 | EXPORT bool sealark_target_has_binding_key(struct node_s *call_expr, 130 | const char *key) 131 | { 132 | #if defined (DEBUG_TRACE) || defined(DEBUG_QUERY) 133 | log_debug("_sealark_target_has_binding_key: %s", key); 134 | #endif 135 | 136 | /* :call-expr[1] > :call-sfx[1] > :arg-list[0] */ 137 | /* then search arg-list children for arg-named/name=str */ 138 | /* :arg-named[0] = :id */ 139 | 140 | /* log_debug("call_expr %d %s", call_expr->tid, */ 141 | /* token_name[call_expr->tid][0]); */ 142 | 143 | struct node_s *call_sfx = utarray_eltptr(call_expr->subnodes, 1); 144 | struct node_s *arg_list = utarray_eltptr(call_sfx->subnodes, 1); 145 | 146 | /* struct node_s *id; */ 147 | int key_len = strlen(key); 148 | 149 | //FIXME: call _get_binding_for_name_unique 150 | 151 | #if defined(DEBUG_UTARRAYS) 152 | log_debug("SEARCHING arg_list %d %s, child ct: %d", 153 | arg_list->tid, 154 | token_name[arg_list->tid][0], 155 | utarray_len(arg_list->subnodes)); 156 | #endif 157 | struct node_s *arg_node = NULL; 158 | struct node_s *id = NULL; 159 | int i = 0; 160 | while((arg_node=(struct node_s*)utarray_next(arg_list->subnodes, 161 | arg_node))) { 162 | #if defined(DEBUG_UTARRAYS) 163 | log_debug(" LOOP arg_list[%d] tid: %d %s", i++, arg_node->tid, 164 | token_name[arg_node->tid][0]); 165 | #endif 166 | if (arg_node->tid == TK_Binding) { // skip TK_COMMA nodes 167 | /* first subnode is TK_ID */ 168 | id = utarray_eltptr(arg_node->subnodes, 0); 169 | /* log_debug("testing id[%d]: %d %s", i, id->tid, id->s); */ 170 | 171 | if ((strncmp(id->s, key, key_len) == 0) 172 | && strlen(id->s) == key_len ){ 173 | /* log_debug("true"); */ 174 | return true; 175 | } 176 | } 177 | } 178 | /* log_debug("false"); */ 179 | return false; 180 | } 181 | 182 | EXPORT bool sealark_target_has_name(struct node_s *call_expr, 183 | const char *name) 184 | { 185 | #if defined (DEBUG_TRACE) || defined(DEBUG_QUERY) 186 | log_debug("_sealark_target_has_name %s", name); 187 | #endif 188 | 189 | /* :call-expr[1] > :call-sfx[1] > :arg-list[0] */ 190 | /* then search arg-list children for arg-named/name=str */ 191 | /* :arg-named[0] = :id */ 192 | 193 | /* log_debug("call_expr %d %s", call_expr->tid, */ 194 | /* token_name[call_expr->tid][0]); */ 195 | 196 | struct node_s *call_sfx = utarray_eltptr(call_expr->subnodes, 1); 197 | struct node_s *arg_list = utarray_eltptr(call_sfx->subnodes, 1); 198 | 199 | /* struct node_s *id; */ 200 | int name_len = strlen(name); 201 | 202 | #if defined(DEBUG_QUERY) 203 | log_debug("SEARCHING arg_list %d %s, child ct: %d", 204 | arg_list->tid, 205 | token_name[arg_list->tid][0], 206 | utarray_len(arg_list->subnodes)); 207 | #endif 208 | struct node_s *arg_node = NULL; 209 | struct node_s *id = NULL; 210 | struct node_s *val = NULL; 211 | int i = 0; 212 | while((arg_node=(struct node_s*)utarray_next(arg_list->subnodes, 213 | arg_node))) { 214 | #if defined(DEBUG_QUERY) 215 | log_debug(" LOOP arg_list[%d] tid: %d %s", i++, arg_node->tid, 216 | token_name[arg_node->tid][0]); 217 | #endif 218 | if (arg_node->tid == TK_Binding) { // skip TK_COMMA nodes 219 | /* first subnode is TK_ID */ 220 | id = utarray_eltptr(arg_node->subnodes, 0); 221 | /* log_debug("testing id[%d]: %d %s", i, id->tid, id->s); */ 222 | 223 | if ((strncmp(id->s, "name", 4) == 0) 224 | && strlen(id->s) == 4 ){ 225 | val = utarray_eltptr(arg_node->subnodes, 2); 226 | if ((strncmp(val->s, name, name_len) == 0) 227 | && strlen(val->s) == name_len ){ 228 | return true; 229 | } 230 | } 231 | } 232 | } 233 | log_debug("false"); 234 | return false; 235 | } 236 | 237 | /* rule may contain final glob, e.g. 'cc_*' */ 238 | EXPORT bool sealark_target_is_rule_kind(struct node_s *call_expr, 239 | const char *rule_kind) 240 | { 241 | #if defined(DEBUG_QUERY) 242 | /* log_debug("sealark_target_is_rule_kind: %s", rule_kind); */ 243 | #endif 244 | 245 | char *rule; 246 | 247 | int rule_len = strlen(rule_kind); 248 | bool globbing = false; 249 | 250 | if (rule_kind[rule_len-1] == '*') { 251 | globbing = true; 252 | rule = calloc(rule_len - 1, sizeof(char)); 253 | strncpy(rule, rule_kind, rule_len-1); 254 | rule[rule_len] = '\0'; 255 | rule_len--; 256 | } else { 257 | rule = (char*)rule_kind; 258 | } 259 | 260 | struct node_s *id = utarray_eltptr(call_expr->subnodes, 0); 261 | /* log_debug("call expr rule: %s", id->s); */ 262 | 263 | if (globbing) { 264 | if (strncmp(id->s, rule, rule_len) == 0) { 265 | free(rule); 266 | return true; 267 | } else { 268 | return false; 269 | } 270 | } else { 271 | if ( (strncmp(id->s, rule, rule_len) == 0) 272 | && (strlen(id->s) == rule_len) ) { 273 | /* log_debug("target has kind %s", rule); */ 274 | return true; 275 | } else { 276 | /* log_debug("target does note have kind %s", rule); */ 277 | return false; 278 | } 279 | } 280 | } 281 | -------------------------------------------------------------------------------- /src/sealark_procs.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | #include "log.h" 9 | #include "utarray.h" 10 | #include "utstring.h" 11 | 12 | #include "sealark_procs.h" 13 | 14 | EXPORT UT_array *sealark_proc_bindings_to_utarray(struct node_s *target) 15 | { 16 | #if defined (DEBUG_TRACE) || defined(DEBUG_QUERY) 17 | log_debug("sealark_target_bindings"); 18 | #endif 19 | assert(target->tid == TK_Call_Expr); 20 | /* log_debug("target tid: %d %s", target->tid, TIDNAME(target)); */ 21 | 22 | /* :call-expr[1] => :call-sfx[1] => :arg-list */ 23 | struct node_s *call_sfx = utarray_eltptr(target->subnodes, 1); 24 | struct node_s *arg_list = utarray_eltptr(call_sfx->subnodes, 1); 25 | 26 | #if defined(DEBUG_AST) 27 | sealark_debug_log_ast_outline(arg_list, 0); 28 | #endif 29 | UT_array *attribs; 30 | utarray_new(attribs, &node_icd); 31 | 32 | struct node_s *nd=NULL; 33 | while( (nd=(struct node_s*)utarray_next(arg_list->subnodes, nd)) ) { 34 | if (nd->tid == TK_Binding) 35 | utarray_push_back(attribs, nd); 36 | } 37 | /* log_debug("found %d bindings (named args)", utarray_len(attribs)); */ 38 | return attribs; 39 | } 40 | 41 | -------------------------------------------------------------------------------- /src/sealark_targets.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | #include "log.h" 9 | #include "utarray.h" 10 | #include "utstring.h" 11 | 12 | #include "sealark_targets.h" 13 | 14 | EXPORT UT_array *sealark_targets_for_pkg(struct node_s *pkg) 15 | { 16 | #if defined (DEBUG_TRACE) || defined(DEBUG_QUERY) 17 | log_debug("sealark_targets_for_pkg"); 18 | #endif 19 | assert(pkg->tid == TK_Package); 20 | // :package > :stmt-list :smallstmt-list > expr-list > call-expr 21 | 22 | /* sealark_debug_log_ast_outline(pkg, 0); */ 23 | 24 | struct node_s *stmt_list = utarray_eltptr(pkg->subnodes, 0); 25 | 26 | /* skip leading comment lines to get to small_stmt_list */ 27 | struct node_s *small_list; 28 | int stmt_list_subnode_ct = utarray_len(stmt_list->subnodes); 29 | for (int i = 0; i < stmt_list_subnode_ct; i++) { 30 | small_list = utarray_eltptr(stmt_list->subnodes, i); 31 | if (small_list->tid == TK_Small_Stmt_List) 32 | break; 33 | } 34 | /* struct node_s *small_list = utarray_eltptr(stmt_list->subnodes, 0); */ 35 | /* log_debug("small_list child ct: %d", utarray_len(small_list->subnodes)); */ 36 | 37 | // each call_expr is wrapped in expr_list 38 | 39 | /* target_exprs will be freed when gc calls g_destroy_ast_nodelist? */ 40 | UT_array *target_list; 41 | utarray_new(target_list, &node_icd); 42 | 43 | struct node_s *exprs=NULL; 44 | struct node_s *target; 45 | #if defined(DEBUG_UTARRAYS) 46 | log_debug("SEARCHING %s (%d), child ct: %d for %s (%d)", 47 | TIDNAME(small_list), 48 | small_list->tid, 49 | utarray_len(small_list->subnodes), 50 | token_name[TK_Expr_List][0], 51 | TK_Expr_List); 52 | #endif 53 | 54 | int small_list_subnode_ct = utarray_len(small_list->subnodes); 55 | /* log_debug("small_list_subnode_ct: %d", small_list_subnode_ct); */ 56 | 57 | int i = 0; 58 | while((exprs 59 | =(struct node_s*)utarray_next(small_list->subnodes, exprs))) { 60 | #if defined(DEBUG_UTARRAYS) 61 | log_debug(" LOOP (fetch) %d: %s (%d)", 62 | i++, TIDNAME(exprs), exprs->tid); 63 | #endif 64 | if (exprs->tid == TK_Expr_List) { 65 | target = utarray_eltptr(exprs->subnodes, 0); 66 | // target is TK_Call_Expr 67 | node_s *binding = sealark_target_binding_for_key(target, "name"); 68 | if (binding) { 69 | utarray_push_back(target_list, target); 70 | } 71 | } else { 72 | /* ignore non-targets */ 73 | } 74 | i++; 75 | } 76 | 77 | /* FIXME: put this in a node->subnodes. need new node type? 78 | TK_Targets? would have to be virtual since targets may be 79 | interspersed with other productions in a file. */ 80 | /* log_debug("found %d targets", utarray_len(target_list)); */ 81 | return target_list; 82 | } 83 | 84 | /* ********************************* */ 85 | EXPORT 86 | struct node_s *sealark_target_for_name(struct node_s *package, 87 | const char *name) 88 | { 89 | #if defined (DEBUG_TRACE) || defined(DEBUG_PATHS) 90 | log_debug("sealark_target_for_name: %s", name); 91 | #endif 92 | struct node_s *t = _target_for_predicate(package, name, -1); 93 | if (t) 94 | return t; 95 | else 96 | return NULL; 97 | } 98 | 99 | /* ********************************** */ 100 | //FIXME: rename sealark_pkg_target_for_int 101 | EXPORT 102 | struct node_s *sealark_target_for_index(struct node_s *package, int i) 103 | { 104 | #if defined (DEBUG_TRACE) || defined(DEBUG_QUERY) 105 | log_debug("sealark_target_for_index %d", i); 106 | #endif 107 | return _target_for_predicate(package, NULL, i); 108 | } 109 | 110 | /* **************************************************************** */ 111 | LOCAL struct node_s *_target_for_predicate(struct node_s *package, 112 | const char *name, int i) 113 | { 114 | #if defined (DEBUG_TRACE) 115 | log_debug("_target_for_predicate: name %s, index %d", name, i); 116 | #endif 117 | 118 | /* if build file starts with comment lines, then the ast will look 119 | like: 120 | 0: TK_Package 96 121 | 1: TK_Stmt_List 131 122 | 2: TK_Stmt 130 123 | 3: TK_COMMENT 16: # comment 1 124 | 2: TK_Stmt 130 125 | 3: TK_COMMENT 16: ## comment 2 126 | 2: TK_Small_Stmt_List 129 127 | 3: TK_Expr_List 109 128 | ... # load stmts, targets ... 129 | 130 | otherwise: 131 | 0: TK_Package 96 132 | 1: TK_Stmt_List 131 133 | 2: TK_Small_Stmt_List 129 134 | 3: TK_Expr_List 109 (package directive) 135 | ... 136 | 3: TK_Load_Stmt 117 137 | ... 138 | 3: TK_Expr_List 109 139 | 4: TK_Call_Expr 97 (target) 140 | ... 141 | 142 | so to get targets we need to skip this initial comments (TK_stmt) 143 | */ 144 | 145 | struct node_s *node = NULL; 146 | struct node_s *expr_nd=NULL; 147 | struct node_s *target_nd=NULL; 148 | 149 | int name_len; 150 | if (name) name_len = strlen(name); 151 | 152 | int target_ct = 0; 153 | 154 | struct node_s *stmt_list = utarray_eltptr(package->subnodes, 0); 155 | 156 | /* struct node_s *small_list = utarray_eltptr(stmt_list->subnodes, 0); */ 157 | 158 | // each call_expr is wrapped in expr_list 159 | /* we cannot just take the ith child, we have to take the ith 160 | target. toplevel children include load stmts, etc. */ 161 | 162 | /* 163 | indexing by int: if index i < 0, we have no way of knowing 164 | target ct without iterating. then we have to iterate again to 165 | get the item. 166 | */ 167 | 168 | while( (node=(struct node_s*)utarray_next(stmt_list->subnodes, 169 | node)) ) { 170 | /* log_debug("tid: %d %s", node->tid, TIDNAME(node)); */ 171 | if (node->tid == TK_Stmt) { // comment lines at start of file 172 | continue; 173 | } 174 | if (node->tid != TK_Small_Stmt_List) { 175 | log_error("Unexpected node type %d %s; expected %d %s", 176 | node->tid, TIDNAME(node), 177 | TK_Small_Stmt_List, token_name[TK_Small_Stmt_List][0]); 178 | return NULL; 179 | } 180 | 181 | while( (expr_nd=(struct node_s*)utarray_next(node->subnodes, 182 | expr_nd)) ) { 183 | 184 | if (expr_nd->tid != TK_Expr_List) { 185 | continue; 186 | } 187 | if (utarray_len(expr_nd->subnodes) > 1) { 188 | log_error("Unexpected number of subnodes for TK_Expr_List: %d", 189 | utarray_len(expr_nd->subnodes)); 190 | exit(EXIT_FAILURE); 191 | } 192 | 193 | target_nd = utarray_front(expr_nd->subnodes); 194 | /* while( (target_nd=(struct node_s*)utarray_next(expr_nd->subnodes, */ 195 | /* target_nd)) ) { */ 196 | 197 | if (name) { /* index by name */ 198 | bool ok = sealark_target_has_binding(target_nd, 199 | "name", name); 200 | if (ok) { 201 | /* log_debug("found target for name: %s", name); */ 202 | return target_nd; 203 | } 204 | } else { /* index by int */ 205 | /* is this a proper target? */ 206 | if (sealark_target_has_binding_key(target_nd, "name")) { 207 | /* log_debug("tgt_ct: %d i: %d", tgt_ct, i); */ 208 | if (target_ct == i) { 209 | /* log_debug("MATCH"); */ 210 | return target_nd; 211 | } 212 | 213 | target_ct++; 214 | } 215 | } 216 | /* } */ 217 | } 218 | } 219 | /* log_debug("target_ct: %d", target_ct); */ 220 | 221 | if (name == NULL) { /* we're indexing by int */ 222 | /* reverse indexing */ 223 | if (i < 0) { 224 | if (abs(i) > target_ct) { 225 | log_error("abs(%d) > target count", i); 226 | errno = EINDEX_OUT_OF_BOUNDS; 227 | return NULL; 228 | } else { 229 | i = target_ct + i; 230 | return sealark_target_for_index(package, i); 231 | } 232 | } 233 | 234 | if (i > target_ct-1) { 235 | log_error("index > target count"); 236 | errno = EINDEX_OUT_OF_BOUNDS; 237 | } 238 | } 239 | if (name) { /* we had a name but could not match it */ 240 | log_warn("target %s not found", name); 241 | errno = ENOT_FOUND; 242 | return NULL; /* not found */ 243 | } 244 | /* should not reach here? */ 245 | log_error("UNEXPECTED FALLTHRU"); 246 | } 247 | 248 | 249 | EXPORT int sealark_target_bindings_count(struct node_s *target) 250 | { 251 | #if defined (DEBUG_TRACE) || defined(DEBUG_QUERY) 252 | log_debug("sealark_target_bindings_count"); 253 | #endif 254 | 255 | UT_array *bindings = sealark_proc_bindings_to_utarray(target); 256 | int ct = utarray_len(bindings); 257 | utarray_free(bindings); 258 | return ct; 259 | } 260 | 261 | /* **************** */ 262 | EXPORT struct node_s *sealark_target_name(struct node_s *target) 263 | { 264 | /* #if defined (DEBUG_TRACE) || defined(DEBUG_QUERY) */ 265 | /* log_debug("sealark_target_name"); */ 266 | /* #endif */ 267 | 268 | assert(target->tid == TK_Call_Expr); 269 | 270 | /* :call-expr[1] > :call-sfx[1] > :arg-list */ 271 | /* :arg-list - for targets, list of bindings */ 272 | /* for ordinary fn application could be anything */ 273 | 274 | UT_string *buf; 275 | utstring_new(buf); 276 | sealark_display_node(target, buf, 0); 277 | utstring_free(buf); 278 | 279 | struct node_s *call_sfx = utarray_eltptr(target->subnodes, 1); 280 | struct node_s *arg_list = utarray_eltptr(call_sfx->subnodes, 1); 281 | 282 | #if defined(DEBUG_UTARRAYS) 283 | log_debug("SEARCHING arg_list %d %s, child ct: %d", 284 | arg_list->tid, 285 | token_name[arg_list->tid][0], 286 | utarray_len(arg_list->subnodes)); 287 | #endif 288 | struct node_s *arg_node = NULL; 289 | struct node_s *id = NULL; 290 | struct node_s *val = NULL; 291 | int i = 0; 292 | while((arg_node=(struct node_s*)utarray_next(arg_list->subnodes, 293 | arg_node))) { 294 | #if defined(DEBUG_UTARRAYS) 295 | log_debug(" LOOP arg_list[%d] tid: %d %s", i++, 296 | arg_node->tid, token_name[arg_node->tid][0]); 297 | #endif 298 | 299 | if (arg_node->tid == TK_Binding) { // skip TK_COMMA nodes 300 | /* first subnode is TK_ID */ 301 | id = utarray_eltptr(arg_node->subnodes, 0); 302 | #if defined(DEBUG_UTARRAYS) 303 | log_debug("testing id[%d]: %d %s", i, id->tid, id->s); 304 | #endif 305 | if ((strncmp(id->s, "name", 4) == 0) 306 | && strlen(id->s) == 4 ){ 307 | val = utarray_eltptr(arg_node->subnodes, 2); 308 | return val; 309 | } 310 | } else { 311 | log_debug("0 xxxxxxxxxxxxxxxx"); 312 | } 313 | } 314 | return NULL; 315 | } 316 | -------------------------------------------------------------------------------- /test/BUILD.bazel: -------------------------------------------------------------------------------- 1 | load("@rules_cc//cc:defs.bzl", "cc_library") 2 | 3 | load("@makeheaders//src:RULES.bzl", "makeheaders") 4 | 5 | TOOLCHAINS = ["//:module_profiles"] 6 | 7 | test_suite( 8 | name = "test", 9 | tests = [ 10 | "//test/sys", 11 | "//test/unit/parser", 12 | "//test/unit/sealark", 13 | ]) 14 | 15 | ################################################################ 16 | ## testing lexis, syntaxis 17 | cc_binary( 18 | name = "lex_file", 19 | srcs = [ 20 | "lex_file.c", 21 | ":mkhdrs" 22 | ], 23 | copts = select({ 24 | # strdup is non-standard, not supported on linux in strict c11 mode 25 | "//bzl/host:macos": ["-std=c11"], 26 | "//bzl/host:linux": ["-std=gnu11"], 27 | "//conditions:default": ["-std=c11"], 28 | }) + [ 29 | "-pedantic-errors", 30 | 31 | "-I", "$(GENDIR)/src", 32 | "-I", "$(GENDIR)/test", 33 | 34 | "-I$(@liblogc)//src", 35 | "-I$(@uthash)//src", 36 | ], 37 | defines = ["DEBUG", "DEBUG_TRACE"], 38 | deps = [ 39 | "//src:sealark", 40 | "@liblogc//src:logc", 41 | "@uthash//src:uthash" 42 | ], 43 | # linkopts = select({ 44 | # "//bzl/host:linux": [], 45 | # "//bzl/host:macos": ["-framework", "CoreServices"], 46 | # }), 47 | linkstatic = 1, 48 | toolchains = TOOLCHAINS 49 | ) 50 | 51 | ########## 52 | cc_binary( 53 | name = "parse_file", 54 | srcs = [ 55 | "parse_file.c", 56 | ":mkhdrs" 57 | # "//src:sealark_debug.c", 58 | ], 59 | copts = select({ 60 | # strdup is non-standard, not supported on linux in strict c11 mode 61 | "//bzl/host:macos": ["-std=c11"], 62 | "//bzl/host:linux": ["-std=gnu11"], 63 | "//conditions:default": ["-std=c11"], 64 | }) + [ 65 | "-pedantic-errors", 66 | 67 | "-I$(GENDIR)/test", 68 | "-I$(GENDIR)/external/sealark/test", 69 | 70 | "-I$(GENDIR)/src", 71 | "-I$(@liblogc)//src", 72 | "-I$(@uthash)//src", 73 | ], 74 | defines = ["DEBUG", "DEBUG_TRACE"], 75 | deps = [ 76 | "//src:sealark", 77 | "@liblogc//src:logc", 78 | "@uthash//src:uthash" 79 | ], 80 | linkstatic = 1, 81 | toolchains = TOOLCHAINS 82 | ) 83 | 84 | ############ 85 | makeheaders( 86 | name = "mkhdrs", 87 | hdrs_srcs = [ 88 | "lex_file.c", 89 | "parse_file.c", 90 | ], 91 | additional_srcs = [ 92 | "//src:sealark.h", 93 | ], 94 | visibility = ["//visibility:public"] 95 | ) 96 | -------------------------------------------------------------------------------- /test/data/BUILD.bazel: -------------------------------------------------------------------------------- 1 | exports_files(glob(["BUILD.*", "*.BUILD"])) 2 | -------------------------------------------------------------------------------- /test/data/BUILD.binding_get: -------------------------------------------------------------------------------- 1 | package(default_visibility = ["//visibility:public"]) 2 | 3 | load("@rules_cc//cc:defs.bzl", "cc_binary", "cc_library", "cc_test") 4 | 5 | load( 6 | "@arepo//apkg:afile.bzl", 7 | "arg1c", "arg2c", "arg3c", 8 | key1c = "val1c", 9 | key2c = "val2c", 10 | lastkey3c = "lastval3c", 11 | ) 12 | 13 | DEFINES = ["DEBUG", "FOO"] 14 | 15 | cc_library( 16 | name = "hello-lib", 17 | srcs = ["hello-lib.cc", "howdy.cc", "howdy.h"], 18 | hdrs = ["hello-lib.h"], 19 | defines = DEFINES 20 | ) 21 | 22 | cc_binary( 23 | name = "hello-world", 24 | srcs = ["hello-world.cc", 'hello-singlequotes.cc'], 25 | deps = [":hello-lib"], 26 | ) 27 | 28 | sunlark_test( 29 | name = "vectors", 30 | string_vec = ["a", "b", "c"], 31 | int_vec = [1, 2, 3] 32 | ) 33 | 34 | cc_test( 35 | name = "hello-success_test", 36 | 37 | 38 | srcs = ["hello-world.cc"], 39 | deps = [":hello-lib"], 40 | ) 41 | 42 | cc_test( 43 | name = "hello-fail_test", 44 | srcs = ["hello-fail.cc"], 45 | deps = [":hello-lib"], 46 | ) 47 | 48 | a,b = "foo", "bar" # multiple assignment 49 | 50 | filegroup( 51 | name = "srcs", 52 | srcs = glob(["**"]), 53 | ) 54 | -------------------------------------------------------------------------------- /test/data/android/BUILD.bazel: -------------------------------------------------------------------------------- 1 | exports_files(["BUILD.test"]) 2 | -------------------------------------------------------------------------------- /test/data/android/BUILD.test: -------------------------------------------------------------------------------- 1 | load("@rules_cc//cc:defs.bzl", "cc_library") 2 | 3 | filegroup( 4 | name = "srcs", 5 | srcs = glob(["**"]), 6 | visibility = ["//examples:__pkg__"], 7 | ) 8 | 9 | android_library( 10 | name = "lib", 11 | srcs = ["Lib.java"], 12 | ) 13 | 14 | android_binary( 15 | name = "hello_world", 16 | srcs = glob([ 17 | "MainActivity.java", 18 | "Jni.java", 19 | ]), 20 | manifest = "AndroidManifest.xml", 21 | resource_files = glob(["res/**"]), 22 | deps = [ 23 | ":jni", 24 | ":lib", 25 | "@androidsdk//com.android.support:appcompat-v7-25.0.0", 26 | ], 27 | ) 28 | 29 | cc_library( 30 | name = "jni", 31 | srcs = ["jni.cc"], 32 | deps = [":jni_dep"], 33 | ) 34 | 35 | cc_library( 36 | name = "jni_dep", 37 | srcs = ["jni_dep.cc"], 38 | hdrs = ["jni_dep.h"], 39 | ) 40 | -------------------------------------------------------------------------------- /test/data/brstrings.BUILD: -------------------------------------------------------------------------------- 1 | package(default_visibility = ["//visibility:public"]) 2 | 3 | load("@rules_cc//cc:defs.bzl", "cc_binary", "cc_library", "cc_test") 4 | 5 | cc_library( 6 | name = r"hello-lib", 7 | srcs = [b"hello-lib.cc"], 8 | hdrs = [br"hello-lib.h"], 9 | ) 10 | 11 | cc_binary( 12 | name = """hello-world""", 13 | srcs = ["hello-world.cc"], 14 | deps = [":hello-lib"], 15 | ) 16 | 17 | cc_test( 18 | name = '''hello-success_test''', 19 | srcs = [b'''hello-world.cc'''], 20 | deps = [r''':hello-lib'''], 21 | br = [br''':hello-lib'''], 22 | ) 23 | 24 | cc_test( 25 | name = "hello-fail_test", 26 | srcs = ["hello-fail.cc"], 27 | deps = [":hello-lib"], 28 | ) 29 | 30 | filegroup( 31 | name = "srcs", 32 | srcs = glob(["**"]), 33 | ) 34 | -------------------------------------------------------------------------------- /test/data/cc/BUILD.bazel: -------------------------------------------------------------------------------- 1 | exports_files(["BUILD.test"]) 2 | -------------------------------------------------------------------------------- /test/data/cc/BUILD.test: -------------------------------------------------------------------------------- 1 | package(default_visibility = ["//visibility:public"]) 2 | 3 | load("@rules_cc//cc:defs.bzl", "cc_binary", "cc_library", "cc_test") 4 | 5 | load( 6 | "@arepo//apkg:afile.bzl", 7 | "arg1c", "arg2c", "arg3c", 8 | key1c = "val1c", 9 | key2c = "val2c", 10 | lastkey3c = "lastval3c", 11 | ) 12 | 13 | DEFINES = ["DEBUG", "FOO"] 14 | 15 | cc_library( 16 | name = "hello-lib", 17 | srcs = ["hello-lib.cc", "howdy.cc", "howdy.h"], 18 | hdrs = ["hello-lib.h"], 19 | defines = DEFINES 20 | ) 21 | 22 | cc_binary( 23 | name = "hello-world", 24 | srcs = ["hello-world.cc"], 25 | deps = [":hello-lib-a"], 26 | ) 27 | 28 | cc_test( 29 | name = "hello-success_test", 30 | 31 | 32 | srcs = ["hello-world.cc"], 33 | deps = [":hello-lib-b"], 34 | ) 35 | 36 | cc_test( 37 | name = "hello-fail_test", 38 | srcs = ["hello-fail.cc"], 39 | deps = [":hello-lib-c"], 40 | ) 41 | 42 | a,b = "foo", "bar" # multiple assignment 43 | 44 | filegroup( 45 | name = "srcs", 46 | srcs = glob(["**"]), 47 | ) 48 | -------------------------------------------------------------------------------- /test/data/comments/BUILD.abseil: -------------------------------------------------------------------------------- 1 | # 2 | # Copyright 2017 The Abseil Authors. 3 | # 4 | # Licensed under the Apache License, Version 2.0 (the "License"); 5 | # you may not use this file except in compliance with the License. 6 | # You may obtain a copy of the License at 7 | # 8 | # https://www.apache.org/licenses/LICENSE-2.0 9 | # 10 | # Unless required by applicable law or agreed to in writing, software 11 | # distributed under the License is distributed on an "AS IS" BASIS, 12 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | # See the License for the specific language governing permissions and 14 | # limitations under the License. 15 | 16 | package(default_visibility = ["//visibility:public"]) 17 | 18 | licenses(["notice"]) 19 | 20 | config_setting( 21 | name = "clang_compiler", 22 | flag_values = { 23 | "@bazel_tools//tools/cpp:compiler": "clang", 24 | }, 25 | visibility = [":__subpackages__"], 26 | ) 27 | 28 | config_setting( 29 | name = "msvc_compiler", 30 | flag_values = { 31 | "@bazel_tools//tools/cpp:compiler": "msvc-cl", 32 | }, 33 | visibility = [":__subpackages__"], 34 | ) 35 | 36 | config_setting( 37 | name = "clang-cl_compiler", 38 | flag_values = { 39 | "@bazel_tools//tools/cpp:compiler": "clang-cl", 40 | }, 41 | visibility = [":__subpackages__"], 42 | ) 43 | 44 | config_setting( 45 | name = "osx", 46 | constraint_values = [ 47 | "@platforms//os:osx", 48 | ], 49 | ) 50 | 51 | config_setting( 52 | name = "ios", 53 | constraint_values = [ 54 | "@platforms//os:ios", 55 | ], 56 | ) 57 | 58 | config_setting( 59 | name = "ppc", 60 | values = { 61 | "cpu": "ppc", 62 | }, 63 | visibility = [":__subpackages__"], 64 | ) 65 | 66 | config_setting( 67 | name = "wasm", 68 | values = { 69 | "cpu": "wasm32", 70 | }, 71 | visibility = [":__subpackages__"], 72 | ) 73 | -------------------------------------------------------------------------------- /test/data/comments/BUILD.bazel: -------------------------------------------------------------------------------- 1 | exports_files(["BUILD.test"]) 2 | -------------------------------------------------------------------------------- /test/data/comments/BUILD.shell_command: -------------------------------------------------------------------------------- 1 | # A small example that takes a text file and generates modified versions of it, 2 | # and metadata about it. These rules depend on unix shell commands like `tr` 3 | # and `stat`. 4 | # 5 | # Build with: 6 | # bazel build //shell_command:* 7 | 8 | load(":rules.bzl", "convert_to_uppercase", "emit_size") 9 | 10 | emit_size( 11 | name = "foo", 12 | file = "foo.txt", 13 | ) 14 | 15 | convert_to_uppercase( 16 | name = "make_uppercase", 17 | input = "foo.txt", 18 | output = "upper_foo.txt", 19 | ) 20 | -------------------------------------------------------------------------------- /test/data/comments/BUILD.test: -------------------------------------------------------------------------------- 1 | cc_library( # comment1 2 | name = "hello-lib", #comment2 3 | srcs = ["hello-lib.cc"], 4 | hdrs = ["hello-lib.h"], 5 | ) 6 | -------------------------------------------------------------------------------- /test/data/comments/BUILD.test1: -------------------------------------------------------------------------------- 1 | # comment1 2 | cc_library( 3 | name = "hello-lib" 4 | ) 5 | -------------------------------------------------------------------------------- /test/data/comments/BUILD.test2: -------------------------------------------------------------------------------- 1 | cc_library( # comment1 2 | # comment 2 3 | name = "hello-lib" 4 | ) 5 | -------------------------------------------------------------------------------- /test/data/dictionaries/BUILD.actions_run: -------------------------------------------------------------------------------- 1 | # from bazel/examples/rules/actions_run 2 | 3 | concat( 4 | name = "sh", 5 | out = "page.html", 6 | chunks = [ 7 | "header.html", 8 | "body.html", 9 | "footer.html", 10 | ], 11 | merge_tool = select({ 12 | "//conditions:default": "//actions_run:merge_on_linux", 13 | "on_linux": "//actions_run:merge_on_linux", 14 | "on_windows": "//actions_run:merge_on_windows.bat", 15 | }), 16 | ) 17 | -------------------------------------------------------------------------------- /test/data/dictionaries/BUILD.bazel: -------------------------------------------------------------------------------- 1 | exports_files(glob(["BUILD.*"])) 2 | -------------------------------------------------------------------------------- /test/data/dictionaries/BUILD.test1: -------------------------------------------------------------------------------- 1 | # comment1 2 | cc_library( 3 | name = "hello-lib" 4 | ) 5 | -------------------------------------------------------------------------------- /test/data/dictionaries/BUILD.test2: -------------------------------------------------------------------------------- 1 | cc_library( # comment1 2 | # comment 2 3 | name = "hello-lib" 4 | ) 5 | -------------------------------------------------------------------------------- /test/data/filegroup/BUILD.bazel: -------------------------------------------------------------------------------- 1 | exports_files(glob(["BUILD.*"])) 2 | -------------------------------------------------------------------------------- /test/data/filegroup/BUILD.test: -------------------------------------------------------------------------------- 1 | package(default_visibility = ["//visibility:public"]) 2 | 3 | filegroup( 4 | name = "srcs", 5 | srcs = glob(["**"]) + [ 6 | "//examples/android/java/bazel:srcs", 7 | "//examples/cpp:srcs", 8 | "//examples/gen:srcs", 9 | "//examples/java-native:srcs", 10 | "//examples/java-skylark:srcs", 11 | "//examples/py:srcs", 12 | "//examples/py_native:srcs", 13 | "//examples/shell:srcs", 14 | "//examples/windows/dll:srcs", 15 | ], 16 | ) 17 | -------------------------------------------------------------------------------- /test/data/genrules/BUILD.bazel: -------------------------------------------------------------------------------- 1 | exports_files(glob(["BUILD.*"])) 2 | -------------------------------------------------------------------------------- /test/data/genrules/BUILD.lib_sexp: -------------------------------------------------------------------------------- 1 | ## from ocml-uri repo 2 | 3 | 4 | ######## 5 | genrule( 6 | name = "gendriver", 7 | outs = ["ppxlib_driver.ml"], 8 | cmd = "\n".join([ 9 | "echo \"(* GENERATED FILE - DO NOT EDIT *)\" > \"$@\"", 10 | "echo \"let () = Ppxlib.Driver.standalone ()\" >> \"$@\"", 11 | ]), 12 | ) 13 | -------------------------------------------------------------------------------- /test/data/genrules/BUILD.test1: -------------------------------------------------------------------------------- 1 | package(default_visibility = ["//visibility:public"]) 2 | 3 | genquery( 4 | name = "genquery", 5 | expression = "deps(@bazel_tools//tools/jdk:current_java_runtime)", 6 | scope = ["@bazel_tools//tools/jdk:current_java_runtime"], 7 | ) 8 | 9 | genrule( 10 | name = "genrule", 11 | srcs = [":genquery"], 12 | outs = ["genrule.txt"], 13 | cmd = "cat $(SRCS) > $@", 14 | ) 15 | 16 | filegroup( 17 | name = "srcs", 18 | srcs = [ 19 | "BUILD", 20 | ], 21 | ) 22 | -------------------------------------------------------------------------------- /test/data/java/BUILD.bazel: -------------------------------------------------------------------------------- 1 | exports_files(["BUILD.test"]) 2 | -------------------------------------------------------------------------------- /test/data/java/BUILD.native: -------------------------------------------------------------------------------- 1 | load("@rules_java//java:defs.bzl", "java_binary", "java_library") 2 | 3 | package(default_visibility = ["//visibility:public"]) 4 | 5 | java_binary( 6 | name = "hello-world", 7 | main_class = "com.example.myproject.Greeter", 8 | runtime_deps = [":hello-lib"], 9 | ) 10 | 11 | java_library( 12 | name = "hello-lib", 13 | srcs = glob( 14 | ["*.java"], 15 | exclude = ["HelloErrorProne.java"], 16 | ), 17 | ) 18 | 19 | java_binary( 20 | name = "hello-resources", 21 | main_class = "com.example.myproject.Greeter", 22 | runtime_deps = [":custom-greeting"], 23 | ) 24 | 25 | java_library( 26 | name = "custom-greeting", 27 | srcs = ["Greeter.java"], 28 | resources = ["//examples/java-native/src/main/resources:greeting"], 29 | ) 30 | 31 | java_library( 32 | name = "hello-error-prone", 33 | srcs = ["HelloErrorProne.java"], 34 | ) 35 | 36 | filegroup( 37 | name = "srcs", 38 | srcs = ["BUILD"] + glob(["**/*.java"]), 39 | ) 40 | -------------------------------------------------------------------------------- /test/data/java/BUILD.skylark: -------------------------------------------------------------------------------- 1 | load("//tools/build_rules:java_rules_skylark.bzl", "java_binary", "java_library") 2 | 3 | package(default_visibility = ["//visibility:public"]) 4 | 5 | java_binary( 6 | name = "hello-world", 7 | srcs = ["Greeter.java"], 8 | main_class = "com.example.myproject.Greeter", 9 | ) 10 | 11 | java_binary( 12 | name = "hello-data", 13 | main_class = "com.example.myproject.Greeter", 14 | deps = [":hello-lib"], 15 | ) 16 | 17 | java_library( 18 | name = "hello-lib", 19 | srcs = ["Greeter.java"], 20 | data = ["//examples/java-skylark/src/main/resources:greeting"], 21 | ) 22 | 23 | filegroup( 24 | name = "srcs", 25 | srcs = ["BUILD"] + glob(["**/*.java"]), 26 | ) 27 | -------------------------------------------------------------------------------- /test/data/java/BUILD.test: -------------------------------------------------------------------------------- 1 | package(default_visibility = ["//visibility:public"]) 2 | 3 | load("@rules_cc//cc:defs.bzl", "cc_binary", "cc_library", "cc_test") 4 | 5 | java_library( 6 | name = "mylib", 7 | srcs = glob(["*.java"]) + [":gen_java_srcs"], 8 | deps = "...", 9 | ) -------------------------------------------------------------------------------- /test/data/large/BUILD.bazel: -------------------------------------------------------------------------------- 1 | exports_files(["BUILD.test"]) 2 | -------------------------------------------------------------------------------- /test/data/large/BUILD.test: -------------------------------------------------------------------------------- 1 | package(default_visibility = ["//visibility:public"]) 2 | 3 | load("@rules_cc//cc:defs.bzl", "cc_binary", "cc_library", "cc_test") 4 | 5 | cc_library( 6 | name = "hello-lib", 7 | srcs = ["hello-lib.cc"], 8 | hdrs = ["hello-lib.h"], 9 | ) 10 | 11 | cc_binary( 12 | name = "hello-world", 13 | srcs = ["hello-world.cc"], 14 | deps = [":hello-lib"], 15 | ) 16 | 17 | cc_test( 18 | name = "hello-success_test", 19 | srcs = ["hello-world.cc"], 20 | deps = [":hello-lib"], 21 | ) 22 | 23 | cc_test( 24 | name = "hello-fail_test", 25 | srcs = ["hello-fail.cc"], 26 | deps = [":hello-lib"], 27 | ) 28 | 29 | filegroup( 30 | name = "srcs", 31 | srcs = glob(["**"]), 32 | ) 33 | 34 | cc_library( 35 | name = "hello-lib", 36 | srcs = ["hello-lib.cc"], 37 | hdrs = ["hello-lib.h"], 38 | ) 39 | 40 | cc_binary( 41 | name = "hello-world", 42 | srcs = ["hello-world.cc"], 43 | deps = [":hello-lib"], 44 | ) 45 | 46 | cc_test( 47 | name = "hello-success_test", 48 | srcs = ["hello-world.cc"], 49 | deps = [":hello-lib"], 50 | ) 51 | 52 | cc_test( 53 | name = "hello-fail_test", 54 | srcs = ["hello-fail.cc"], 55 | deps = [":hello-lib"], 56 | ) 57 | 58 | filegroup( 59 | name = "srcs", 60 | srcs = glob(["**"]), 61 | ) 62 | 63 | cc_library( 64 | name = "hello-lib", 65 | srcs = ["hello-lib.cc"], 66 | hdrs = ["hello-lib.h"], 67 | ) 68 | 69 | cc_binary( 70 | name = "hello-world", 71 | srcs = ["hello-world.cc"], 72 | deps = [":hello-lib"], 73 | ) 74 | 75 | cc_test( 76 | name = "hello-success_test", 77 | srcs = ["hello-world.cc"], 78 | deps = [":hello-lib"], 79 | ) 80 | 81 | cc_test( 82 | name = "hello-fail_test", 83 | srcs = ["hello-fail.cc"], 84 | deps = [":hello-lib"], 85 | ) 86 | 87 | filegroup( 88 | name = "srcs", 89 | srcs = glob(["**"]), 90 | ) 91 | 92 | cc_library( 93 | name = "hello-lib", 94 | srcs = ["hello-lib.cc"], 95 | hdrs = ["hello-lib.h"], 96 | ) 97 | 98 | cc_binary( 99 | name = "hello-world", 100 | srcs = ["hello-world.cc"], 101 | deps = [":hello-lib"], 102 | ) 103 | 104 | cc_test( 105 | name = "hello-success_test", 106 | srcs = ["hello-world.cc"], 107 | deps = [":hello-lib"], 108 | ) 109 | 110 | cc_test( 111 | name = "hello-fail_test", 112 | srcs = ["hello-fail.cc"], 113 | deps = [":hello-lib"], 114 | ) 115 | 116 | filegroup( 117 | name = "srcs", 118 | srcs = glob(["**"]), 119 | ) 120 | 121 | foo( 122 | name = "barrrrrrrrrrrrrrrrr", 123 | ) 124 | -------------------------------------------------------------------------------- /test/data/load/BUILD.args: -------------------------------------------------------------------------------- 1 | load("@repoa//pkga:tgta.bzl", "arg1a", "arg2a") 2 | 3 | load("@repob//pkgb:tgtb.bzl", "arg1b", "arg2b", key1b = "val1b" ) 4 | 5 | package(default_visibility = ["//visibility:public"]) 6 | 7 | load( 8 | "@repoc//pkgc:tgtc.bzl", 9 | "arg1c", "arg2c", "arg3c", 10 | key1c = "val1c", 11 | key2c = "val2c", 12 | lastkey3c = "lastval3c", 13 | ) 14 | 15 | load("@rules_cc//cc:defs.bzl", "cc_binary", "cc_library", "cc_test") 16 | 17 | cc_library( 18 | name = "hello-lib", 19 | srcs = ["hello-lib.cc", 'howdy.cc', r"howdy.h"], 20 | hdrs = ["hello-lib.h"], 21 | ) 22 | 23 | cc_binary( 24 | name = "hello-world", 25 | srcs = ["hello-world.cc"], 26 | deps = [":hello-lib"], 27 | ) 28 | 29 | cc_test( 30 | name = "hello-success_test", 31 | 32 | 33 | srcs = ["hello-world.cc"], 34 | deps = [":hello-lib"], 35 | ) 36 | 37 | cc_test( 38 | name = "hello-fail_test", 39 | srcs = ["hello-fail.cc"], 40 | deps = [":hello-lib"], 41 | ) 42 | -------------------------------------------------------------------------------- /test/data/load/BUILD.bazel: -------------------------------------------------------------------------------- 1 | exports_files(["BUILD.test"]) 2 | -------------------------------------------------------------------------------- /test/data/load/BUILD.test1: -------------------------------------------------------------------------------- 1 | load("@repo1//pkg1:tgt1.bzl", "arg1", "arg2") 2 | -------------------------------------------------------------------------------- /test/data/load/BUILD.test2: -------------------------------------------------------------------------------- 1 | load("@repo1//pkg1:tgt1.bzl", "arg1", "arg2") 2 | 3 | load("@repo2//pkg2:tgt2.bzl", "arg1", "arg2", key1 = "val1" ) 4 | 5 | load( 6 | "@repo3//pkg3:tgt3.bzl", 7 | "var3" 8 | ) 9 | -------------------------------------------------------------------------------- /test/data/load/BUILD.testsq: -------------------------------------------------------------------------------- 1 | load('@repo1//pkg1:tgt1.bzl', 'arg1', 'arg2') 2 | 3 | load('@repo2//pkg2:tgt2.bzl', 'arg1', 'arg2', key1 = 'val1' ) 4 | 5 | load( 6 | '@repo3//pkg3:tgt3.bzl', 7 | 'var3' 8 | ) 9 | -------------------------------------------------------------------------------- /test/data/load/aliases/test1/BUILD.bazel: -------------------------------------------------------------------------------- 1 | exports_files(["BUILD.test"]) 2 | -------------------------------------------------------------------------------- /test/data/load/aliases/test1/BUILD.test: -------------------------------------------------------------------------------- 1 | load("@foo1//bar1:baz1.bzl", v1="var1") 2 | 3 | load("@foo1a//bar1a:baz1a.bzl", v1a = "var1a") 4 | 5 | load( "@foo2//bar2:baz2.bzl", v2="var2" ) 6 | 7 | load( 8 | "@foo3//bar3:baz3.bzl", 9 | v3="var3" 10 | ) 11 | -------------------------------------------------------------------------------- /test/data/load/aliases/test2/BUILD.bazel: -------------------------------------------------------------------------------- 1 | exports_files(["BUILD.test"]) 2 | -------------------------------------------------------------------------------- /test/data/load/aliases/test2/BUILD.test: -------------------------------------------------------------------------------- 1 | # add comments 2 | 3 | load("@foo1//bar1:baz1.bzl", v1="var1") # comment 1 4 | 5 | load( # comment 2 6 | "@foo2//bar2:baz2.bzl", # comment 3 7 | v2="var2" # comment 4 8 | ) 9 | #comment 5 10 | 11 | load( # comment 6 12 | "@foo3//bar3:baz3.bzl", # comment 7 13 | v3 # comment 8 14 | = # comment 9 15 | "var3" # comment 10 16 | ) # comment 11 -------------------------------------------------------------------------------- /test/data/load/comments/BUILD.bazel: -------------------------------------------------------------------------------- 1 | exports_files(["BUILD.test"]) 2 | -------------------------------------------------------------------------------- /test/data/load/comments/BUILD.test: -------------------------------------------------------------------------------- 1 | # line 1 - add comments 2 | 3 | load( "@foo2//bar2:baz2.bzl", "var2" ) # eol comment 4 | 5 | load( # internal comment 1 6 | "@foo3//bar3:baz3.bzl", # internal comment 2 7 | # internal comment 3 8 | "var3" 9 | # internal comment 4 10 | ) 11 | # trailing comment 5 12 | -------------------------------------------------------------------------------- /test/data/load/test2/BUILD.bazel: -------------------------------------------------------------------------------- 1 | exports_files(["BUILD.test"]) 2 | -------------------------------------------------------------------------------- /test/data/load/test2/BUILD.test: -------------------------------------------------------------------------------- 1 | ## test build file 2 | 3 | load( 4 | "@foo//bar:defs.bzl", 5 | "var_a", 6 | alias_b="var_b", 7 | "var_c", 8 | alias_d="var_d" 9 | ) 10 | -------------------------------------------------------------------------------- /test/data/load/test3/BUILD.bazel: -------------------------------------------------------------------------------- 1 | exports_files(["BUILD.test"]) 2 | -------------------------------------------------------------------------------- /test/data/load/test3/BUILD.test: -------------------------------------------------------------------------------- 1 | ## test build file 2 | 3 | load( 4 | "@foo//bar:defs.bzl", 5 | alias_a = "var_a", 6 | # alias_b = "var_b" 7 | ) 8 | -------------------------------------------------------------------------------- /test/data/ocaml/BUILD.bazel: -------------------------------------------------------------------------------- 1 | exports_files(["BUILD.*"]) 2 | -------------------------------------------------------------------------------- /test/data/ocaml/BUILD.test1: -------------------------------------------------------------------------------- 1 | load( 2 | "@obazl_rules_ocaml//ocaml:rules.bzl", 3 | "ocaml_archive", 4 | "ocaml_executable", 5 | "ocaml_module", 6 | ) 7 | 8 | ocaml_executable( 9 | name = "hello", 10 | main = ":main", 11 | # deps = [":main"] 12 | ) 13 | 14 | ocaml_module( 15 | name = "main", 16 | struct = "main.ml", 17 | deps = [":archive"], 18 | ) 19 | 20 | ocaml_module( 21 | name = "easy", 22 | struct = "easy.ml", 23 | ) 24 | 25 | ocaml_module( 26 | foo, 27 | name = "simple", 28 | struct = "simple.ml", 29 | ) 30 | -------------------------------------------------------------------------------- /test/data/python/BUILD.bazel: -------------------------------------------------------------------------------- 1 | exports_files(["BUILD.test"]) 2 | -------------------------------------------------------------------------------- /test/data/python/BUILD.test: -------------------------------------------------------------------------------- 1 | package(default_visibility = ["//visibility:public"]) 2 | 3 | py_library( 4 | name = "lib", 5 | srcs = ["lib.py"], 6 | ) 7 | 8 | py_binary( 9 | name = "bin", 10 | srcs = ["bin.py"], 11 | deps = [":lib"], 12 | ) 13 | 14 | filegroup( 15 | name = "srcs", 16 | srcs = ["BUILD"] + glob(["**/*.py"]) 17 | ) 18 | -------------------------------------------------------------------------------- /test/data/python/native/BUILD.bazel: -------------------------------------------------------------------------------- 1 | exports_files(["BUILD.test"]) 2 | -------------------------------------------------------------------------------- /test/data/python/native/BUILD.test: -------------------------------------------------------------------------------- 1 | filegroup( 2 | name = "srcs", 3 | srcs = glob(["*.py"]) + [ 4 | "BUILD", 5 | "//examples/py_native/fibonacci:srcs", 6 | ], 7 | visibility = ["//examples:__pkg__"], 8 | ) 9 | 10 | py_binary( 11 | name = "bin", 12 | srcs = ["bin.py"], 13 | deps = [ 14 | ":lib", 15 | "//examples/py_native/fibonacci", 16 | ], 17 | ) 18 | 19 | py_library( 20 | name = "lib", 21 | srcs = ["lib.py"], 22 | ) 23 | 24 | py_test( 25 | name = "test", 26 | srcs = ["test.py"], 27 | deps = [ 28 | ":lib", 29 | "//examples/py_native/fibonacci", 30 | ], 31 | ) 32 | 33 | py_test( 34 | name = "fail", 35 | srcs = ["fail.py"], 36 | deps = [":lib"], 37 | ) 38 | -------------------------------------------------------------------------------- /test/data/shell/BUILD.bazel: -------------------------------------------------------------------------------- 1 | exports_files(["BUILD.test"]) 2 | -------------------------------------------------------------------------------- /test/data/shell/BUILD.test: -------------------------------------------------------------------------------- 1 | package(default_visibility = ["//visibility:public"]) 2 | 3 | sh_binary( 4 | name = "bin", 5 | srcs = ["bin.sh"], 6 | deps = [ 7 | ":lib", 8 | "@bazel_tools//tools/bash/runfiles", 9 | ], 10 | ) 11 | 12 | sh_library( 13 | name = "lib", 14 | data = [ 15 | "data/file.txt", 16 | "lib.sh", 17 | ], 18 | deps = ["@bazel_tools//tools/bash/runfiles"], 19 | ) 20 | 21 | sh_test( 22 | name = "test", 23 | size = "small", 24 | srcs = ["test.sh"], 25 | data = ["data/test_file.txt"], 26 | deps = [ 27 | ":lib", 28 | "@bazel_tools//tools/bash/runfiles", 29 | ], 30 | ) 31 | 32 | filegroup( 33 | name = "srcs", 34 | srcs = glob(["**"]), 35 | ) 36 | -------------------------------------------------------------------------------- /test/data/small/BUILD.bazel: -------------------------------------------------------------------------------- 1 | exports_files(["BUILD.test"]) 2 | -------------------------------------------------------------------------------- /test/data/small/BUILD.test1: -------------------------------------------------------------------------------- 1 | package(default_visibility = ["//visibility:public"]) 2 | -------------------------------------------------------------------------------- /test/data/small/BUILD.test2: -------------------------------------------------------------------------------- 1 | package(default_visibility = ["//visibility:public"]) 2 | 3 | load("@rules_cc//cc:defs.bzl", "cc_binary", "cc_library", "cc_test") 4 | 5 | cc_library( 6 | name = "hello-lib", 7 | srcs = ["hello-lib.cc"], 8 | hdrs = ["hello-lib.h"], 9 | ) 10 | -------------------------------------------------------------------------------- /test/data/small/BUILD.test3: -------------------------------------------------------------------------------- 1 | package(default_visibility = ["//visibility:public"]) 2 | 3 | load("@rules_cc//cc:defs.bzl", "cc_binary", "cc_library", "cc_test") 4 | 5 | cc_library( 6 | name = "hello-lib", 7 | srcs = ["hello-lib.cc"], 8 | hdrs = ["hello-lib.h"], 9 | ) 10 | 11 | cc_binary( 12 | name = "hello-world", 13 | srcs = ["hello-world.cc"], 14 | deps = [":hello-lib"], 15 | ) 16 | 17 | cc_test( 18 | name = "hello-success_test", 19 | srcs = ["hello-world.cc"], 20 | deps = [":hello-lib"], 21 | ) 22 | 23 | -------------------------------------------------------------------------------- /test/data/sunlark/BUILD.bazel: -------------------------------------------------------------------------------- 1 | exports_files(["BUILD.test"]) 2 | -------------------------------------------------------------------------------- /test/data/sunlark/BUILD.test: -------------------------------------------------------------------------------- 1 | package(default_visibility = ["//visibility:public"]) 2 | 3 | load("@rules_cc//cc:defs.bzl", "cc_binary", "cc_library", "cc_test") 4 | 5 | cc_library( 6 | name = "hello-lib", 7 | srcs = ["hello-lib.cc"], 8 | hdrs = ["hello-lib.h"], 9 | ) 10 | 11 | cc_binary( 12 | name = "hello-world", 13 | srcs = ["hello-world.cc"], 14 | deps = [":hello-lib"], 15 | ) 16 | 17 | cc_test( 18 | name = "hello-success_test", 19 | srcs = ["hello-world.cc"], 20 | deps = [":hello-lib"], 21 | ) 22 | 23 | cc_test( 24 | name = "hello-fail_test", 25 | srcs = ["hello-fail.cc"], 26 | deps = [":hello-lib"], 27 | ) 28 | 29 | filegroup( 30 | name = "srcs", 31 | srcs = glob(["**"]), 32 | ) 33 | -------------------------------------------------------------------------------- /test/data/walk/BUILD.bazel: -------------------------------------------------------------------------------- 1 | exports_files(glob(["BUILD.*"])) 2 | -------------------------------------------------------------------------------- /test/data/walk/BUILD.complete: -------------------------------------------------------------------------------- 1 | package(default_visibility = ["//visibility:public"]) 2 | 3 | load("@rules_cc//cc:defs.bzl", "cc_binary", "cc_library", "cc_test") 4 | 5 | exports_files(["foo.c"]) 6 | 7 | cc_library( 8 | name = "hello-lib", 9 | bstr = b"binstr", 10 | srcs = ["hello-lib.cc"], 11 | dict_attr = {"foo": "bar"}, 12 | string_attr = "hello!", 13 | deps = [ 14 | ":dep_a", ":dep_b", 15 | ":dep_c", ":dep_d", 16 | ":dep_e", 17 | ], 18 | ) 19 | 20 | cc_binary( 21 | name = "hello-world", 22 | srcs = ["hello-world.cc"], 23 | deps = [":hello-lib"], 24 | ) 25 | 26 | cc_test( 27 | name = "hello-success_test", 28 | srcs = ["hello-world.cc"], 29 | deps = [":hello-lib"], 30 | ) 31 | 32 | filegroup( 33 | name = "srcs", 34 | srcs = glob(["**"]), 35 | ) 36 | -------------------------------------------------------------------------------- /test/data/walk/BUILD.exports: -------------------------------------------------------------------------------- 1 | exports_files(["BUILD.test"]) 2 | -------------------------------------------------------------------------------- /test/data/walk/BUILD.load1: -------------------------------------------------------------------------------- 1 | load("@rules_cc//cc:defs.bzl", "cc_binary", "cc_library", "cc_test") 2 | -------------------------------------------------------------------------------- /test/data/walk/BUILD.load2: -------------------------------------------------------------------------------- 1 | load("@rules_cc//cc:defs.bzl", 2 | bin="cc_binary", 3 | lib="cc_library", 4 | tst="cc_test" 5 | ) 6 | -------------------------------------------------------------------------------- /test/data/walk/BUILD.load3: -------------------------------------------------------------------------------- 1 | load("@rules_cc//cc:defs.bzl", 2 | "cc_binary", 3 | "cc_library", 4 | tst="cc_test" 5 | ) 6 | -------------------------------------------------------------------------------- /test/data/walk/BUILD.load4: -------------------------------------------------------------------------------- 1 | load("Aloader.bzl", "a", "b") 2 | 3 | load("Bloader.bzl", "c", "d") 4 | 5 | load("Cloader.bzl", "e", "f") 6 | 7 | cc_library( 8 | name = "hello-lib", 9 | srcs = ["hello-lib.cc"] 10 | ) 11 | -------------------------------------------------------------------------------- /test/data/walk/BUILD.mix1: -------------------------------------------------------------------------------- 1 | package(default_visibility = ["//visibility:public"]) 2 | 3 | load("@rules_cc//cc:defs.bzl", "cc_binary", "cc_library", "cc_test") 4 | 5 | load("@rules_foo//foo:defs.bzl", "foo_binary", "foo_library", "foo_test") 6 | 7 | cc_library( 8 | name = "hello-lib", 9 | srcs = ["hello-lib.cc"], 10 | ) 11 | 12 | cc_binary( 13 | name = "hello", 14 | deps = [":hello-lib"], 15 | ) 16 | -------------------------------------------------------------------------------- /test/data/walk/BUILD.package: -------------------------------------------------------------------------------- 1 | package(default_visibility = ["//visibility:public"]) 2 | -------------------------------------------------------------------------------- /test/data/walk/BUILD.targets1: -------------------------------------------------------------------------------- 1 | cc_library( name = "hello-lib" ) -------------------------------------------------------------------------------- /test/data/walk/BUILD.targets2: -------------------------------------------------------------------------------- 1 | cc_library( 2 | name = "hello-lib", 3 | srcs = ["hello.c"] 4 | ) 5 | -------------------------------------------------------------------------------- /test/data/walk/BUILD.targets3: -------------------------------------------------------------------------------- 1 | cc_library( name = "a-lib", srcs=["a.c"]) 2 | cc_library( name = "b-lib", srcs=["bsrc1.c", "bsrc2.c"]) 3 | cc_library( name = "c-lib", srcs=["c.c"]) 4 | -------------------------------------------------------------------------------- /test/data/walk/BUILD.targets4: -------------------------------------------------------------------------------- 1 | cc_library( name = "a-lib" ) 2 | cc_binary( name = "a-bin" ) 3 | cc_library( name = "b-lib" ) 4 | cc_library( name = "c-lib" ) 5 | cc_test( 6 | name = "hello-success_test", 7 | srcs = ["hello-world.cc"], 8 | deps = [":hello-lib"], 9 | ) 10 | 11 | cc_test( 12 | name = "hello-fail_test", 13 | srcs = ["hello-fail.cc"], 14 | deps = [":hello-lib"], 15 | ) 16 | 17 | cc_binary( name = "b-bin" ) 18 | -------------------------------------------------------------------------------- /test/data/walk/BUILD.targets5: -------------------------------------------------------------------------------- 1 | cc_library( 2 | name = "hello-lib", 3 | bstr = b"binstr", 4 | srcs = ["hello-lib.cc"], 5 | dict_attr = {"foo": "bar"}, 6 | string_attr = "hello!", 7 | deps = [ 8 | ":dep_a", ":dep_b", 9 | ":dep_c", ":dep_d", 10 | ":dep_e", 11 | ], 12 | ) 13 | -------------------------------------------------------------------------------- /test/data/walk/BUILD.test2: -------------------------------------------------------------------------------- 1 | package(default_visibility = ["//visibility:public"]) 2 | 3 | load("@rules_cc//cc:defs.bzl", "cc_binary", "cc_library", "cc_test") 4 | 5 | cc_library( 6 | name = "hello-lib", 7 | bstr = b"binstr", 8 | srcs = ["hello-lib.cc"], 9 | dict_attr = {"foo": "bar"}, 10 | string_attr = "hello!", 11 | deps = [ 12 | ":dep_a", ":dep_b", 13 | ":dep_c", ":dep_d", 14 | ":dep_e", 15 | ], 16 | ) 17 | -------------------------------------------------------------------------------- /test/data/walk/BUILD.test3: -------------------------------------------------------------------------------- 1 | cc_library( 2 | name = "hello-lib", 3 | bstr = b"binstr", 4 | srcs = ["hello-lib.cc"], 5 | dict_attr = {"foo": "bar"}, 6 | string_attr = "hello!", 7 | deps = [ 8 | ":dep_a", ":dep_b", 9 | ":dep_c", ":dep_d", 10 | ":dep_e", 11 | ], 12 | ) 13 | -------------------------------------------------------------------------------- /test/data/windows/dll/BUILD.bazel: -------------------------------------------------------------------------------- 1 | exports_files(["BUILD.test"]) 2 | -------------------------------------------------------------------------------- /test/data/windows/dll/BUILD.test: -------------------------------------------------------------------------------- 1 | load("//examples/windows/dll:windows_dll_library.bzl", "windows_dll_library") 2 | load("@rules_cc//cc:defs.bzl", "cc_binary") 3 | 4 | filegroup( 5 | name = "srcs", 6 | srcs = glob(["**"]), 7 | visibility = ["//examples:__pkg__"], 8 | ) 9 | 10 | # Define the shared library 11 | windows_dll_library( 12 | name = "hellolib", 13 | srcs = ["hello-library.cpp"], 14 | hdrs = ["hello-library.h"], 15 | # Define COMPILING_DLL to export symbols during compiling the DLL. 16 | # See hello-library.h 17 | copts = ["/DCOMPILING_DLL"], 18 | ) 19 | 20 | # **Explicitly link to hellolib.dll** 21 | 22 | ## Declare hellolib.dll as data dependency and load it explicitly in code. 23 | cc_binary( 24 | name = "hello_world-load-dll-at-runtime", 25 | srcs = ["hello_world-load-dll-at-runtime.cpp"], 26 | data = [":hellolib.dll"], 27 | ) 28 | 29 | # **Implicitly link to hellolib.dll** 30 | 31 | ## Link to hellolib.dll through its import library. 32 | cc_binary( 33 | name = "hello_world-link-to-dll-via-lib", 34 | srcs = ["hello_world-link-to-dll-via-lib.cpp"], 35 | deps = [":hellolib"], 36 | ) 37 | -------------------------------------------------------------------------------- /test/lex_file.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | #if INTERFACE 6 | #ifdef LINUX /* FIXME */ 7 | #include 8 | #else // FIXME: macos test 9 | #include 10 | #endif 11 | #endif 12 | 13 | #include 14 | 15 | #include "log.h" 16 | #include "utarray.h" 17 | #include "utstring.h" 18 | 19 | #if INTERFACE 20 | #include "utstring.h" 21 | #endif 22 | 23 | #include "sealark.h" 24 | 25 | #include "lex_file.h" 26 | 27 | int main(int argc, char *argv[]) 28 | { 29 | int opt; 30 | 31 | UT_string *build_file; 32 | utstring_new(build_file); 33 | 34 | while ((opt = getopt(argc, argv, "f:hv")) != -1) { 35 | switch (opt) { 36 | case 'f': 37 | /* BUILD.bazel or BUILD file */ 38 | utstring_printf(build_file, "%s", optarg); 39 | break; 40 | case 'h': 41 | log_info("Help: "); 42 | exit(EXIT_SUCCESS); 43 | default: 44 | log_error("Usage: %s [-f] [buildfile]", argv[0]); 45 | exit(EXIT_FAILURE); 46 | } 47 | } 48 | 49 | if (utstring_len(build_file) == 0) { 50 | log_error("-f must be provided."); 51 | exit(EXIT_FAILURE); 52 | } 53 | 54 | char *wd = getenv("BUILD_WORKING_DIRECTORY"); 55 | if (wd) { 56 | /* we launched from bazel workspace, cd to launch dir */ 57 | chdir(wd); 58 | } 59 | 60 | UT_array *result = sealark_lex_file(utstring_body(build_file)); 61 | 62 | /* UT_array *result = sealark_lex_string("'hello'\n#cmt1\n"); */ 63 | 64 | log_debug("main RESULT dump:"); 65 | dump_nodes(result); 66 | } 67 | -------------------------------------------------------------------------------- /test/parse_file.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | #if INTERFACE 6 | #ifdef LINUX /* FIXME */ 7 | #include 8 | #else // FIXME: macos test 9 | #include 10 | #endif 11 | #endif 12 | #include 13 | #include 14 | #include 15 | #include 16 | 17 | #include "log.h" 18 | #include "utarray.h" 19 | #include "utstring.h" 20 | 21 | #include "parse_file.h" 22 | 23 | UT_string *build_file; 24 | 25 | UT_string *buffer; 26 | 27 | int compareFiles(FILE *file1, FILE *file2) 28 | { 29 | /* printf("comparing files\n"); */ 30 | char ch1 = getc(file1); 31 | char ch2 = getc(file2); 32 | int error = 0, pos = 0, line = 1; 33 | while (ch1 != EOF && ch2 != EOF){ 34 | pos++; 35 | if (ch1 == '\n' && ch2 == '\n'){ 36 | line++; 37 | pos = 0; 38 | } 39 | if (ch1 != ch2){ 40 | error++; 41 | printf("File mismatch at (%d:%d)\n", line, pos); 42 | return -1; 43 | } 44 | ch1 = getc(file1); 45 | ch2 = getc(file2); 46 | } 47 | return 0; 48 | } 49 | 50 | int main(int argc, char *argv[]) 51 | { 52 | int opt; 53 | utstring_new(build_file); 54 | 55 | while ((opt = getopt(argc, argv, "f:hv")) != -1) { 56 | switch (opt) { 57 | case 'f': 58 | /* BUILD.bazel or BUILD file */ 59 | utstring_printf(build_file, "%s", optarg); 60 | break; 61 | case 'h': 62 | log_info("Help: "); 63 | exit(EXIT_SUCCESS); 64 | default: 65 | log_error("Usage: %s [-f] [buildfile]", argv[0]); 66 | exit(EXIT_FAILURE); 67 | } 68 | } 69 | 70 | if (utstring_len(build_file) == 0) { 71 | log_error("-f must be provided."); 72 | exit(EXIT_FAILURE); 73 | } 74 | 75 | char *wd = getenv("BUILD_WORKING_DIRECTORY"); 76 | if (wd) { 77 | /* we launched from bazel workspace, cd to launch dir */ 78 | chdir(wd); 79 | } 80 | 81 | struct node_s *pkg_node = sealark_parse_file(utstring_body(build_file)); 82 | UT_string *buf = sealark_debug_display_ast_outline(pkg_node, 0); 83 | printf("%s", utstring_body(buf)); 84 | utstring_free(buf); 85 | 86 | /* serialization routines expect a UT_string, not a char buffer */ 87 | utstring_new(buffer); 88 | sealark_node_to_starlark(pkg_node, buffer); 89 | printf("%s", utstring_body(buffer)); 90 | 91 | char *outfile = tmpnam(NULL); 92 | /* printf("serializing to: %s\n", outfile); */ 93 | FILE *fp; 94 | fp = fopen(outfile, "w+"); 95 | if (fp == NULL) { 96 | printf("fopen error: %d\n", errno); 97 | /* } else { */ 98 | /* printf("created test output file: %s\n", outfile); */ 99 | } 100 | int r = fputs(utstring_body(buffer), fp); 101 | if (r < 0) { 102 | printf("error on fputs: %d", errno); 103 | goto cleanup; 104 | } 105 | fclose(fp); 106 | 107 | /* now compare input and output files */ 108 | FILE *file1 = fopen(utstring_body(build_file), "r"); 109 | FILE *file2 = fopen(outfile, "r"); 110 | if (file1 == NULL || file2 == NULL){ 111 | printf("Error : Files not open"); 112 | goto cleanup; 113 | } 114 | r = compareFiles(file1, file2); 115 | if (r < 0) { 116 | printf("mismatch %d, outfile: %s\n", r, outfile); 117 | } else { 118 | printf("match!\n"); 119 | } 120 | fclose(file1); 121 | fclose(file2); 122 | 123 | cleanup: 124 | if (r == 0) { 125 | r = remove(outfile); 126 | if (r < 0) { 127 | printf("remove(%s) failed, rc: %d", outfile, errno); 128 | /* } else { */ 129 | /* printf("removed tmp file %s\n", outfile); */ 130 | } 131 | } else { 132 | printf("tmp outfile: %s\n", outfile); 133 | } 134 | utstring_free(buffer); 135 | /* free(parse_state->lexer->fname); */ 136 | sealark_node_free(pkg_node); 137 | return r; 138 | } 139 | -------------------------------------------------------------------------------- /test/sys/BUILD.bazel: -------------------------------------------------------------------------------- 1 | load("@rules_cc//cc:defs.bzl", "cc_library") 2 | load("@makeheaders//src:RULES.bzl", "makeheaders") 3 | TOOLCHAINS = ["//:test_module_profiles"] 4 | 5 | test_suite( 6 | name = "sys", 7 | tests = [ 8 | ":sealark", 9 | # ":starlark", 10 | ]) 11 | 12 | cc_test( 13 | name = "sealark", 14 | linkstatic = 1, 15 | srcs = [ 16 | "test_starlark.c", 17 | "starlark_roundtrip.c", 18 | ":mkhdrs" 19 | # "//starlark:config.c", 20 | # "test_starlark.h", 21 | # "starlark_roundtrip.h", 22 | # "//starlark:config.h", 23 | ], 24 | data = [ # NB: globbing does not seem to work 25 | # "//test/lua:serialize.lua", 26 | 27 | "//test/data/android:BUILD.test", 28 | "//test/data/cc:BUILD.test", 29 | "//test/data/filegroup:BUILD.bazel", 30 | # "//test/data/gen:BUILD.bazel", 31 | "//test/data/load/aliases/test1:BUILD.test", 32 | "//test/data/load/aliases/test2:BUILD.test", 33 | "//test/data/load/comments:BUILD.test", 34 | # "//test/data/load/test1:BUILD.test", 35 | "//test/data/load/test2:BUILD.test", 36 | "//test/data/load/test3:BUILD.test", 37 | "//test/data/python:BUILD.test", 38 | "//test/data/python/native:BUILD.test", 39 | "//test/data/shell:BUILD.test", 40 | "//test/data/windows/dll:BUILD.test", 41 | ], 42 | copts = select({ 43 | # strdup is non-standard, not supported on linux in strict c11 mode 44 | "//bzl/host:macos": ["-std=c11"], 45 | "//bzl/host:linux": ["-std=gnu11"], 46 | "//conditions:default": ["-std=c11"], 47 | }) + [ 48 | "-pedantic-errors", 49 | 50 | "-I$(GENDIR)/$(@)/src", 51 | "-I$(GENDIR)/$(@)/test/sys", 52 | 53 | # "-I$(GENDIR)/starlark", 54 | # "-I$(GENDIR)/external/starlark/starlark", 55 | 56 | # "-I$(GENDIR)/starlark", 57 | 58 | # "-I", "$(GENDIR)/src/lib/starlark", 59 | # "-I", "$(GENDIR)external/starlark/src/lib/starlark", 60 | 61 | # "-I", "$(GENDIR)/src/lib/starlark", 62 | # "-I", "$(GENDIR)/external/starlark/src/lib/starlark", # libstarlark.h 63 | 64 | "-I$(@liblogc)/src", 65 | "-I$(@uthash)/src", 66 | "-I$(@unity)/src", 67 | 68 | # "-I", "vendored/lua-5.4.3/src", 69 | # "-I", "external/starlark/vendored/lua-5.4.3/src", 70 | 71 | ], 72 | deps = [ 73 | # "//starlark:config", 74 | # "//src/lib/lbazel", 75 | "//src:sealark", 76 | "@liblogc//src:logc", 77 | "@unity//src:unity", 78 | "@uthash//src:uthash", 79 | # pulled in by starlark 80 | # "//vendored/lua-5.4.3/src:lua", 81 | ], 82 | toolchains = TOOLCHAINS 83 | ) 84 | 85 | # cc_test( 86 | # name = "starlark", 87 | # srcs = [ 88 | # "test_starlark.c", 89 | # "starlark_roundtrip.c", 90 | # ":mkhdrs" 91 | # # "test_starlark.h", 92 | # # "starlark_roundtrip.h", 93 | # ], 94 | # data = [ # NB: globbing does not seem to work 95 | # "//test/data/android:BUILD.bazel", 96 | # "//test/data/cpp:BUILD.bazel", 97 | # "//test/data/filegroup:BUILD.bazel", 98 | # "//test/data/gen:BUILD.bazel", 99 | # "//test/data/load/aliases/test1:BUILD.bazel", 100 | # "//test/data/load/aliases/test2:BUILD.bazel", 101 | # "//test/data/load/comments:BUILD.bazel", 102 | # "//test/data/load/test1:BUILD.bazel", 103 | # "//test/data/load/test2:BUILD.bazel", 104 | # "//test/data/load/test3:BUILD.bazel", 105 | # "//test/data/python:BUILD.bazel", 106 | # "//test/data/python/native:BUILD.bazel", 107 | # "//test/data/shell:BUILD.bazel", 108 | # "//test/data/windows/dll:BUILD.bazel", 109 | # ], 110 | # copts = select({ 111 | # # strdup is non-standard, not supported on linux in strict c11 mode 112 | # "//bzl/host:macos": ["-std=c11"], 113 | # "//bzl/host:linux": ["-std=gnu11"], 114 | # "//conditions:default": ["-std=c11"], 115 | # }) + [ 116 | # "-pedantic-errors", 117 | 118 | # "-I$(GENDIR)/src/lib/starlark", 119 | # "-I$(GENDIR)/test/sys", 120 | # "-I$(@liblogc)/src", 121 | # "-I$(@unity)/src", 122 | # "-I$(@uthash)/src", 123 | 124 | # # "-Ivendored/logc", 125 | # # "-Ivendored/unity", 126 | 127 | # # "-I", "vendored/uthash", 128 | # # "-I", "external/starlark/vendored/uthash", 129 | # ], 130 | # deps = [ 131 | # "//src/lib/starlark", 132 | # "@liblogc//src:logc", 133 | # "@unity//src:unity", 134 | # "@uthash//src:uthash" 135 | # ], 136 | # toolchains = TOOLCHAINS 137 | # ) 138 | 139 | ################################################################ 140 | makeheaders( 141 | name = "mkhdrs", 142 | hdrs_srcs = [ 143 | # "//starlark:config.c", 144 | "//src:sealark_debug.c", 145 | # "//src/lib/lbazel:lbazel.c", 146 | "starlark_roundtrip.c", 147 | "test_starlark.c" 148 | ], 149 | # outs = [ 150 | # "starlark_roundtrip.h", 151 | # "starlark_roundtrip.h", 152 | # "test_starlark.h", 153 | # "test_starlark.h", 154 | # # "lex_keywords.h", 155 | # # "lex_numbers.h", 156 | # # "lex_punctuation.h", 157 | # # "lex_strings.h", 158 | # # "syntax_call_expr.h", 159 | # # "syntax_dict.h", 160 | # # "syntax_expressions.h", 161 | # # "syntax_lists.h", 162 | # # "syntax_slices.h", 163 | # # "syntax_statements.h", 164 | # ], 165 | # cmd = "\n".join([ 166 | # "SRC1=$(location starlark_roundtrip.c)", 167 | # "SRCDIR1=`dirname $$SRC1`", 168 | # "$(location //vendored/makeheaders) \\", 169 | # " $(location //starlark:config.c) \\", 170 | # " $(location //src/lib/lbazel:lbazel.c) \\", 171 | # " $(location //src/lib/starlark:debug.c) \\", 172 | # " $(location starlark_roundtrip.c) \\", 173 | # " $(location starlark_roundtrip.c) \\", 174 | # " $(location test_starlark.c) \\", 175 | # " $(location test_starlark.c)", 176 | # # " $(location lex_keywords.c) \\", 177 | # # " $(location lex_numbers.c) \\", 178 | # # " $(location lex_punctuation.c) \\", 179 | # # " $(location lex_strings.c) \\", 180 | # # " $(location syntax_call_expr.c) \\", 181 | # # " $(location syntax_dict.c) \\", 182 | # # " $(location syntax_expressions.c) \\", 183 | # # " $(location syntax_lists.c) \\", 184 | # # " $(location syntax_slices.c) \\", 185 | # # " $(location syntax_statements.c)", 186 | # "cp $${SRCDIR1}/*.h $(@D)", 187 | # ]), 188 | # tools = ["//vendored/makeheaders"], 189 | visibility = ["//visibility:public"] 190 | ) 191 | -------------------------------------------------------------------------------- /test/sys/starlark_roundtrip.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #include "log.h" 5 | #include "utarray.h" 6 | #include "utstring.h" 7 | #include "unity.h" 8 | #include "sealark.h" 9 | /* #include "syntaxis.h" */ 10 | 11 | #include "starlark_roundtrip.h" 12 | 13 | UT_string *build_file; 14 | 15 | UT_string *buffer; 16 | 17 | int compareFiles(FILE *file1, FILE *file2) 18 | { 19 | char ch1 = getc(file1); 20 | char ch2 = getc(file2); 21 | int error = 0, pos = 0, line = 1; 22 | while (ch1 != EOF && ch2 != EOF){ 23 | pos++; 24 | if (ch1 == '\n' && ch2 == '\n'){ 25 | line++; 26 | pos = 0; 27 | } 28 | if (ch1 != ch2){ 29 | error++; 30 | printf("File mismatch at (%d:%d)\n", line, pos); 31 | return -1; 32 | } 33 | ch1 = getc(file1); 34 | ch2 = getc(file2); 35 | } 36 | return 0; 37 | } 38 | 39 | int roundtrip(char *_file) 40 | { 41 | char *wd = getenv("BUILD_WORKING_DIRECTORY"); 42 | if (wd) { 43 | log_info("BUILD_WORKING_DIRECTORY: %s", wd); 44 | chdir(wd); 45 | } else { 46 | log_info("BUILD_WORKING_DIRECTORY not found"); 47 | } 48 | 49 | char cwd[PATH_MAX]; 50 | if (getcwd(cwd, sizeof(cwd)) != NULL) { 51 | log_info("Current working dir: %s\n", cwd); 52 | } else { 53 | perror("getcwd() error"); 54 | return 1; 55 | } 56 | 57 | utstring_renew(build_file); 58 | 59 | utstring_printf(build_file, "%s", _file); 60 | 61 | struct node_s *parse = sealark_parse_file(utstring_body(build_file)); 62 | log_debug("parsed file %s", utstring_body(build_file)); 63 | /* dump_node(root); */ 64 | 65 | /* serialization routines expect a UT_string, not a char buffer */ 66 | utstring_renew(buffer); 67 | sealark_node_to_starlark(parse, buffer); 68 | /* printf("%s", utstring_body(buffer)); */ 69 | 70 | // FIXME: use mkstemp instead of tmpnam 71 | char *outfile = tmpnam(NULL); 72 | /* printf("outfile name: %s\n", outfile); */ 73 | FILE *fp; 74 | fp = fopen(outfile, "w+"); 75 | if (fp == NULL) { 76 | printf("fopen error: %d\n", errno); 77 | /* } else { */ 78 | /* printf("created test output file: %s\n", outfile); */ 79 | } 80 | int r = fputs(utstring_body(buffer), fp); 81 | if (r < 0) { 82 | printf("error on fputs: %d", errno); 83 | goto cleanup; 84 | } 85 | fclose(fp); 86 | 87 | /* now compare input and output files */ 88 | FILE *file1 = fopen(utstring_body(build_file), "r"); 89 | FILE *file2 = fopen(outfile, "r"); 90 | if (file1 == NULL || file2 == NULL){ 91 | printf("Error : Files not open"); 92 | goto cleanup; 93 | } 94 | static int diff; 95 | diff = compareFiles(file1, file2); 96 | if (diff < 0) { 97 | printf("MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\n"); 98 | log_fatal("mismatch at %d for\n\t%s and\n\t%s\n", 99 | r, 100 | utstring_body(build_file), 101 | outfile); 102 | } else { 103 | printf("MATCH!\n"); 104 | } 105 | 106 | fclose(file1); 107 | fclose(file2); 108 | 109 | cleanup: 110 | if (diff == 0) { 111 | r = remove(outfile); 112 | if (r < 0) { 113 | printf("remove(%s) failed, rc: %d", outfile, errno); 114 | /* } else { */ 115 | /* printf("removed tmp file %s\n", outfile); */ 116 | } 117 | } 118 | sealark_node_free(parse); 119 | /* node_dtor(parse->root); */ 120 | return diff; // r; 121 | } 122 | -------------------------------------------------------------------------------- /test/sys/test_starlark.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #include "log.h" 5 | #include "utarray.h" 6 | #include "utstring.h" 7 | #include "unity.h" 8 | 9 | #include "test_starlark.h" 10 | 11 | UT_string *build_file; 12 | 13 | UT_string *buffer; 14 | 15 | void setUp(void) { 16 | utstring_new(build_file); 17 | utstring_new(buffer); 18 | } 19 | 20 | void tearDown(void) { 21 | utstring_free(build_file); 22 | utstring_free(buffer); 23 | } 24 | 25 | void test_android(void) { 26 | TEST_ASSERT_MESSAGE( 27 | roundtrip("test/data/android/BUILD.test") == EXIT_SUCCESS, 28 | "Mismatch on test/data/android/BUILD.test" 29 | ); 30 | } 31 | 32 | void test_cc(void) { 33 | TEST_ASSERT_MESSAGE( 34 | roundtrip("test/data/cc/BUILD.test") == EXIT_SUCCESS, 35 | "Mismatch on test/data/cc/BUILD.test" 36 | ); 37 | } 38 | 39 | void test_general_rules(void) { 40 | TEST_ASSERT_MESSAGE( 41 | roundtrip("test/data/filegroup/BUILD.test") == EXIT_SUCCESS, 42 | "Mismatch on test/data/filegroup/BUILD.test" 43 | ); 44 | 45 | TEST_ASSERT_MESSAGE( 46 | roundtrip("test/data/genrules/BUILD.test1") == EXIT_SUCCESS, 47 | "Mismatch on test/data/genrules/BUILD.test1" 48 | ); 49 | } 50 | 51 | void test_load(void) { 52 | TEST_ASSERT_MESSAGE( 53 | roundtrip("test/data/load/BUILD.test1") == EXIT_SUCCESS, 54 | "Mismatch on test/data/load/BUILD.test1" 55 | ); 56 | TEST_ASSERT_MESSAGE( 57 | roundtrip("test/data/load/BUILD.test2") == EXIT_SUCCESS, 58 | "Mismatch on test/data/load/BUILD.test2" 59 | ); 60 | TEST_ASSERT_MESSAGE( 61 | roundtrip("test/data/load/BUILD.testsq") == EXIT_SUCCESS, 62 | "Mismatch on test/data/load/BUILD.testsq" 63 | ); 64 | TEST_ASSERT_MESSAGE( 65 | roundtrip("test/data/load/BUILD.args") == EXIT_SUCCESS, 66 | "Mismatch on test/data/load/BUILD.args" 67 | ); 68 | /* TEST_ASSERT_MESSAGE( */ 69 | /* roundtrip("test/data/load/_aliases_2.BUILD") == EXIT_SUCCESS, */ 70 | /* "Mismatch on test/data/load/_aliases_2.BUILD" */ 71 | /* ); */ 72 | } 73 | 74 | void test_python(void) { 75 | /* TEST_ASSERT_MESSAGE( */ 76 | /* roundtrip("test/data/py.BUILD") == EXIT_SUCCESS, */ 77 | /* "Mismatch on test/data/py.BUILD" */ 78 | /* ); */ 79 | 80 | TEST_ASSERT_MESSAGE( 81 | roundtrip("test/data/python/native/BUILD.test") == EXIT_SUCCESS, 82 | "Mismatch on test/data/python/native/BUILD.test" 83 | ); 84 | } 85 | 86 | void test_shell(void) { 87 | TEST_ASSERT_MESSAGE( 88 | roundtrip("test/data/shell/BUILD.test") == EXIT_SUCCESS, 89 | "Mismatch on test/data/shell/BUILD.test" 90 | ); 91 | } 92 | 93 | void test_windows(void) { 94 | TEST_ASSERT_MESSAGE( 95 | roundtrip("test/data/windows/dll/BUILD.test") == EXIT_SUCCESS, 96 | "Mismatch on test/data/windows/dll/BUILD.test" 97 | ); 98 | } 99 | 100 | int main(void) { 101 | UNITY_BEGIN(); 102 | RUN_TEST(test_android); 103 | RUN_TEST(test_cc); 104 | RUN_TEST(test_general_rules); 105 | RUN_TEST(test_load); 106 | RUN_TEST(test_python); 107 | RUN_TEST(test_shell); 108 | RUN_TEST(test_windows); 109 | return UNITY_END(); 110 | } 111 | -------------------------------------------------------------------------------- /test/unit/parser/BUILD.bazel: -------------------------------------------------------------------------------- 1 | load("@rules_cc//cc:defs.bzl", "cc_library") 2 | load("@makeheaders//src:RULES.bzl", "makeheaders") 3 | TOOLCHAINS = ["//:test_module_profiles"] 4 | 5 | test_suite( 6 | name = "parser", 7 | tests = [ 8 | ":call", 9 | ":dict", 10 | ":expressions", 11 | ":keywords", 12 | ":lists", 13 | ":numbers", 14 | ":punctuation", 15 | ":slices", 16 | ":statements", 17 | ":strings", 18 | ]) 19 | 20 | # LEXIS 21 | cc_test( 22 | name = "keywords", 23 | srcs = [ 24 | "lex_keywords.c", 25 | ":mkhdrs" 26 | ], 27 | copts = select({ 28 | # strdup is non-standard, not supported on linux in strict c11 mode 29 | "//bzl/host:macos": ["-std=c11"], 30 | "//bzl/host:linux": ["-std=gnu11"], 31 | "//conditions:default": ["-std=c11"], 32 | }) + [ 33 | "-pedantic-errors", 34 | "-I$(GENDIR)/$(@)/src", 35 | "-I$(GENDIR)/$(@)/test/unit/parser", 36 | "-I$(@liblogc)/src", 37 | "-I$(@unity)/src", 38 | "-I$(@uthash)/src", 39 | ], 40 | linkstatic = 1, 41 | deps = [ 42 | "//src:sealark", 43 | "@liblogc//src:logc", 44 | "@unity//src:unity", 45 | "@uthash//src:uthash" 46 | ], 47 | timeout = "short", 48 | toolchains = TOOLCHAINS 49 | ) 50 | 51 | cc_test( 52 | name = "numbers", 53 | srcs = [ 54 | "lex_numbers.c", 55 | ":mkhdrs" 56 | ], 57 | copts = select({ 58 | # strdup is non-standard, not supported on linux in strict c11 mode 59 | "//bzl/host:macos": ["-std=c11"], 60 | "//bzl/host:linux": ["-std=gnu11"], 61 | "//conditions:default": ["-std=c11"], 62 | }) + [ 63 | "-pedantic-errors", 64 | 65 | "-I$(GENDIR)/$(@)/src", 66 | "-I$(GENDIR)/$(@)/test/unit/parser", 67 | 68 | "-I$(@liblogc)/src", 69 | "-I$(@unity)/src", 70 | "-I$(@uthash)/src", 71 | ], 72 | linkstatic = 1, 73 | deps = [ 74 | "//src:sealark", 75 | "@liblogc//src:logc", 76 | "@unity//src:unity", 77 | "@uthash//src:uthash" 78 | ], 79 | timeout = "short", 80 | toolchains = TOOLCHAINS 81 | ) 82 | 83 | cc_test( 84 | name = "punctuation", 85 | srcs = [ 86 | "lex_punctuation.c", 87 | ":mkhdrs" 88 | ], 89 | copts = select({ 90 | # strdup is non-standard, not supported on linux in strict c11 mode 91 | "//bzl/host:macos": ["-std=c11"], 92 | "//bzl/host:linux": ["-std=gnu11"], 93 | "//conditions:default": ["-std=c11"], 94 | }) + [ 95 | "-pedantic-errors", 96 | 97 | "-I$(GENDIR)/$(@)/src", 98 | "-I$(GENDIR)/$(@)/test/unit/parser", 99 | 100 | "-I$(@liblogc)/src", 101 | "-I$(@unity)/src", 102 | "-I$(@uthash)/src", 103 | ], 104 | linkstatic = 1, 105 | deps = [ 106 | "//src:sealark", 107 | "@liblogc//src:logc", 108 | "@unity//src:unity", 109 | "@uthash//src:uthash" 110 | ], 111 | timeout = "short", 112 | toolchains = TOOLCHAINS 113 | ) 114 | 115 | cc_test( 116 | name = "strings", 117 | srcs = [ 118 | "lex_strings.c", 119 | ":mkhdrs" 120 | ], 121 | copts = select({ 122 | # strdup is non-standard, not supported on linux in strict c11 mode 123 | "//bzl/host:macos": ["-std=c11"], 124 | "//bzl/host:linux": ["-std=gnu11"], 125 | "//conditions:default": ["-std=c11"], 126 | }) + [ 127 | "-pedantic-errors", 128 | 129 | "-I$(GENDIR)/$(@)/src", 130 | "-I$(GENDIR)/$(@)/test/unit/parser", 131 | 132 | "-I$(@liblogc)/src", 133 | "-I$(@unity)/src", 134 | "-I$(@uthash)/src", 135 | ], 136 | linkstatic = 1, 137 | deps = [ 138 | "//src:sealark", 139 | "@liblogc//src:logc", 140 | "@unity//src:unity", 141 | "@uthash//src:uthash" 142 | ], 143 | timeout = "short", 144 | toolchains = TOOLCHAINS 145 | ) 146 | 147 | # SYNTAX 148 | cc_test( 149 | name = "call", 150 | srcs = [ 151 | "syntax_call_expr.c", 152 | ":mkhdrs" 153 | ], 154 | copts = select({ 155 | # strdup is non-standard, not supported on linux in strict c11 mode 156 | "//bzl/host:macos": ["-std=c11"], 157 | "//bzl/host:linux": ["-std=gnu11"], 158 | "//conditions:default": ["-std=c11"], 159 | }) + [ 160 | "-pedantic-errors", 161 | 162 | "-I$(GENDIR)/$(@)/src", 163 | "-I$(GENDIR)/$(@)/test/unit/parser", 164 | 165 | "-I$(@liblogc)/src", 166 | "-I$(@unity)/src", 167 | "-I$(@uthash)/src", 168 | ], 169 | linkstatic = 1, 170 | deps = [ 171 | "//src:sealark", 172 | "@liblogc//src:logc", 173 | "@unity//src:unity", 174 | "@uthash//src:uthash" 175 | ], 176 | timeout = "short", 177 | toolchains = TOOLCHAINS 178 | ) 179 | 180 | cc_test( 181 | name = "dict", 182 | srcs = [ 183 | "syntax_dict.c", 184 | ":mkhdrs" 185 | ], 186 | copts = select({ 187 | # strdup is non-standard, not supported on linux in strict c11 mode 188 | "//bzl/host:macos": ["-std=c11"], 189 | "//bzl/host:linux": ["-std=gnu11"], 190 | "//conditions:default": ["-std=c11"], 191 | }) + [ 192 | "-pedantic-errors", 193 | 194 | "-I$(GENDIR)/$(@)/src", 195 | "-I$(GENDIR)/$(@)/test/unit/parser", 196 | 197 | "-I$(@liblogc)/src", 198 | "-I$(@unity)/src", 199 | "-I$(@uthash)/src", 200 | ], 201 | linkstatic = 1, 202 | deps = [ 203 | "//src:sealark", 204 | "@liblogc//src:logc", 205 | "@unity//src:unity", 206 | "@uthash//src:uthash" 207 | ], 208 | timeout = "short", 209 | toolchains = TOOLCHAINS 210 | ) 211 | 212 | cc_test( 213 | name = "expressions", 214 | srcs = [ 215 | "syntax_expressions.c", 216 | ":mkhdrs" 217 | ], 218 | copts = select({ 219 | # strdup is non-standard, not supported on linux in strict c11 mode 220 | "//bzl/host:macos": ["-std=c11"], 221 | "//bzl/host:linux": ["-std=gnu11"], 222 | "//conditions:default": ["-std=c11"], 223 | }) + [ 224 | "-pedantic-errors", 225 | 226 | "-I$(GENDIR)/$(@)/src", 227 | "-I$(GENDIR)/$(@)/test/unit/parser", 228 | 229 | "-I$(@liblogc)/src", 230 | "-I$(@unity)/src", 231 | "-I$(@uthash)/src", 232 | ], 233 | linkstatic = 1, 234 | deps = [ 235 | "//src:sealark", 236 | "@liblogc//src:logc", 237 | "@unity//src:unity", 238 | "@uthash//src:uthash" 239 | ], 240 | timeout = "short", 241 | toolchains = TOOLCHAINS 242 | ) 243 | 244 | cc_test( 245 | name = "lists", 246 | srcs = [ 247 | "syntax_lists.c", 248 | ":mkhdrs" 249 | ], 250 | copts = select({ 251 | # strdup is non-standard, not supported on linux in strict c11 mode 252 | "//bzl/host:macos": ["-std=c11"], 253 | "//bzl/host:linux": ["-std=gnu11"], 254 | "//conditions:default": ["-std=c11"], 255 | }) + [ 256 | "-pedantic-errors", 257 | 258 | "-I$(GENDIR)/$(@)/src", 259 | "-I$(GENDIR)/$(@)/test/unit/parser", 260 | 261 | "-I$(@liblogc)/src", 262 | "-I$(@unity)/src", 263 | "-I$(@uthash)/src", 264 | ], 265 | linkstatic = 1, 266 | deps = [ 267 | "//src:sealark", 268 | "@liblogc//src:logc", 269 | "@unity//src:unity", 270 | "@uthash//src:uthash" 271 | ], 272 | timeout = "short", 273 | toolchains = TOOLCHAINS 274 | ) 275 | 276 | cc_test( 277 | name = "slices", 278 | srcs = [ 279 | "syntax_slices.c", 280 | ":mkhdrs" 281 | ], 282 | copts = select({ 283 | # strdup is non-standard, not supported on linux in strict c11 mode 284 | "//bzl/host:macos": ["-std=c11"], 285 | "//bzl/host:linux": ["-std=gnu11"], 286 | "//conditions:default": ["-std=c11"], 287 | }) + [ 288 | "-pedantic-errors", 289 | 290 | "-I$(GENDIR)/$(@)/src", 291 | "-I$(GENDIR)/$(@)/test/unit/parser", 292 | 293 | "-I$(@liblogc)/src", 294 | "-I$(@unity)/src", 295 | "-I$(@uthash)/src", 296 | ], 297 | linkstatic = 1, 298 | deps = [ 299 | "//src:sealark", 300 | "@liblogc//src:logc", 301 | "@unity//src:unity", 302 | "@uthash//src:uthash" 303 | ], 304 | timeout = "short", 305 | toolchains = TOOLCHAINS 306 | ) 307 | 308 | cc_test( 309 | name = "statements", 310 | srcs = [ 311 | "syntax_statements.c", 312 | ":mkhdrs" 313 | ], 314 | copts = select({ 315 | # strdup is non-standard, not supported on linux in strict c11 mode 316 | "//bzl/host:macos": ["-std=c11"], 317 | "//bzl/host:linux": ["-std=gnu11"], 318 | "//conditions:default": ["-std=c11"], 319 | }) + [ 320 | "-pedantic-errors", 321 | 322 | "-I$(GENDIR)/$(@)/src", 323 | "-I$(GENDIR)/$(@)/test/unit/parser", 324 | 325 | "-I$(@liblogc)/src", 326 | "-I$(@unity)/src", 327 | "-I$(@uthash)/src", 328 | ], 329 | linkstatic = 1, 330 | deps = [ 331 | "//src:sealark", 332 | "@liblogc//src:logc", 333 | "@unity//src:unity", 334 | "@uthash//src:uthash" 335 | ], 336 | timeout = "short", 337 | toolchains = TOOLCHAINS 338 | ) 339 | 340 | ################################################################ 341 | makeheaders( 342 | name = "mkhdrs", 343 | hdrs_srcs = [ 344 | "//src:sealark_debug.c", 345 | # "roundtrip_starlark.c", 346 | # "roundtrip_moonlark.c", 347 | # "roundtrip_helper.c", 348 | "lex_keywords.c", 349 | "lex_numbers.c", 350 | "lex_punctuation.c", 351 | "lex_strings.c", 352 | "syntax_call_expr.c", 353 | "syntax_dict.c", 354 | "syntax_expressions.c", 355 | "syntax_lists.c", 356 | "syntax_slices.c", 357 | "syntax_statements.c", 358 | # "lex_file.c", 359 | # "lua_file.c", 360 | # "parse_file.c", 361 | ], 362 | # outs = [ 363 | # "lex_keywords.h", 364 | # "lex_numbers.h", 365 | # "lex_punctuation.h", 366 | # "lex_strings.h", 367 | # "syntax_call_expr.h", 368 | # "syntax_dict.h", 369 | # "syntax_expressions.h", 370 | # "syntax_lists.h", 371 | # "syntax_slices.h", 372 | # "syntax_statements.h", 373 | # # "lex_file.h", 374 | # # "lua_file.h", 375 | # # "parse_file.h", 376 | # ], 377 | # cmd = "\n".join([ 378 | # "SRC1=$(location lex_strings.c)", 379 | # "SRCDIR1=`dirname $$SRC1`", 380 | # "$(location //vendored/makeheaders) \\", 381 | # " $(location //sealark:debug.c) \\", 382 | # " $(location lex_keywords.c) \\", 383 | # " $(location lex_numbers.c) \\", 384 | # " $(location lex_punctuation.c) \\", 385 | # " $(location lex_strings.c) \\", 386 | # " $(location syntax_call_expr.c) \\", 387 | # " $(location syntax_dict.c) \\", 388 | # " $(location syntax_expressions.c) \\", 389 | # " $(location syntax_lists.c) \\", 390 | # " $(location syntax_slices.c) \\", 391 | # " $(location syntax_statements.c)", 392 | # # " $(location lex_file.c) \\", 393 | # # " $(location lua_file.c) \\", 394 | # # " $(location parse_file.c)", 395 | # "cp $${SRCDIR1}/*.h $(@D)", 396 | # ]), 397 | # tools = ["//vendored/makeheaders"], 398 | visibility = ["//visibility:public"] 399 | ) 400 | -------------------------------------------------------------------------------- /test/unit/parser/lex_keywords.c: -------------------------------------------------------------------------------- 1 | #include "utarray.h" 2 | #include "utstring.h" 3 | #include "unity.h" 4 | #include "sealark.h" 5 | 6 | #include "lex_keywords.h" 7 | 8 | UT_string *buf; 9 | UT_string *test_s; 10 | UT_array *result; 11 | 12 | LOCAL const int tk[] = { 13 | TK_AND, TK_OR, 14 | TK_IF, TK_ELSE, TK_ELIF, 15 | TK_LOAD, TK_FOR, 16 | TK_NOT, TK_CONTINUE, 17 | TK_DEF, TK_IN, 18 | TK_PASS, TK_BREAK, 19 | TK_LAMBDA, TK_RETURN, 20 | /* RESERVED */ 21 | TK_AS, TK_IMPORT, 22 | TK_ASSERT, TK_IS, 23 | TK_CLASS, TK_NONLOCAL, 24 | TK_DEL, TK_RAISE, 25 | TK_EXCEPT, TK_TRY, 26 | TK_FINALLY, TK_WHILE, 27 | TK_FROM, TK_WITH, 28 | TK_GLOBAL, TK_YIELD 29 | }; 30 | 31 | void setUp(void) { 32 | utstring_new(test_s); 33 | utstring_new(buf); 34 | } 35 | 36 | void tearDown(void) { 37 | utstring_free(test_s); 38 | utstring_free(buf); 39 | } 40 | 41 | void test_kw(void) { 42 | for (int i=0; i < 16; i++) { 43 | /* printf("punct %s: :]%s[:\n", */ 44 | /* token_name[tk[i]][0], token_name[tk[i]][1]); */ 45 | utstring_renew(test_s); 46 | utstring_printf(test_s, "%s\n", 47 | token_name[tk[i]][1]); 48 | /* printf(utstring_body(test_s)); */ 49 | result = sealark_lex_string(utstring_body(test_s)); 50 | utstring_renew(buf); 51 | sealark_nodelist2string(result, buf); 52 | /* printf(utstring_body(buf)); */ 53 | TEST_ASSERT_EQUAL_STRING(utstring_body(test_s), utstring_body(buf)); 54 | utarray_free(result); 55 | } 56 | } 57 | 58 | void test_kw_cmt(void) { 59 | for (int i=0; i < 16; i++) { 60 | /* printf("tok %s: :]%s[:\n", */ 61 | /* token_name[tk[i]][0], token_name[tk[i]][1]); */ 62 | utstring_renew(test_s); 63 | utstring_printf(test_s, "%s%s", 64 | token_name[tk[i]][1], 65 | " #cmt1\n"); 66 | /* printf(utstring_body(test_s)); */ 67 | result = sealark_lex_string(utstring_body(test_s)); 68 | utstring_renew(buf); 69 | sealark_nodelist2string(result, buf); 70 | /* printf(utstring_body(buf)); */ 71 | TEST_ASSERT_EQUAL_STRING(utstring_body(test_s), utstring_body(buf)); 72 | utarray_free(result); 73 | } 74 | } 75 | 76 | void test_kw_nl_cmt(void) { 77 | for (int i=0; i < 16; i++) { 78 | /* printf("punct %s: :]%s[:\n", */ 79 | /* token_name[tk[i]][0], token_name[tk[i]][1]); */ 80 | utstring_renew(test_s); 81 | utstring_printf(test_s, "%s%s", 82 | token_name[tk[i]][1], 83 | "\n #cmt1\n"); 84 | /* printf(utstring_body(test_s)); */ 85 | result = sealark_lex_string(utstring_body(test_s)); 86 | utstring_renew(buf); 87 | sealark_nodelist2string(result, buf); 88 | /* printf(utstring_body(buf)); */ 89 | TEST_ASSERT_EQUAL_STRING(utstring_body(test_s), utstring_body(buf)); 90 | utarray_free(result); 91 | } 92 | } 93 | 94 | void test_kw_cmt_nl2_cmt(void) { 95 | for (int i=0; i < 16; i++) { 96 | /* printf("punct %s: :]%s[:\n", */ 97 | /* token_name[tk[i]][0], token_name[tk[i]][1]); */ 98 | utstring_renew(test_s); 99 | utstring_printf(test_s, "%s%s", 100 | token_name[tk[i]][1], 101 | "\n\n #cmt1\n"); 102 | /* printf(utstring_body(test_s)); */ 103 | result = sealark_lex_string(utstring_body(test_s)); 104 | utstring_renew(buf); 105 | sealark_nodelist2string(result, buf); 106 | /* printf(utstring_body(buf)); */ 107 | TEST_ASSERT_EQUAL_STRING(utstring_body(test_s), utstring_body(buf)); 108 | utarray_free(result); 109 | } 110 | } 111 | 112 | void test_kw_nl_cmt_nl_cmt(void) { 113 | for (int i=0; i < 16; i++) { 114 | /* printf("punct %s: :]%s[:\n", */ 115 | /* token_name[tk[i]][0], token_name[tk[i]][1]); */ 116 | utstring_renew(test_s); 117 | utstring_printf(test_s, "%s%s", 118 | token_name[tk[i]][1], 119 | "\n #cmt1\n #cmt2\n"); 120 | /* printf(utstring_body(test_s)); */ 121 | result = sealark_lex_string(utstring_body(test_s)); 122 | utstring_renew(buf); 123 | sealark_nodelist2string(result, buf); 124 | /* printf(utstring_body(buf)); */ 125 | TEST_ASSERT_EQUAL_STRING(utstring_body(test_s), utstring_body(buf)); 126 | utarray_free(result); 127 | } 128 | } 129 | 130 | void test_kw_nl2_cmt_nl_cmt(void) { 131 | for (int i=0; i < 16; i++) { 132 | /* printf("punct %s: :]%s[:\n", */ 133 | /* token_name[tk[i]][0], token_name[tk[i]][1]); */ 134 | utstring_renew(test_s); 135 | utstring_printf(test_s, "%s%s", 136 | token_name[tk[i]][1], 137 | "\n\n #cmt1\n #cmt2\n"); 138 | /* printf(utstring_body(test_s)); */ 139 | result = sealark_lex_string(utstring_body(test_s)); 140 | utstring_renew(buf); 141 | sealark_nodelist2string(result, buf); 142 | /* printf(utstring_body(buf)); */ 143 | TEST_ASSERT_EQUAL_STRING(utstring_body(test_s), utstring_body(buf)); 144 | utarray_free(result); 145 | } 146 | } 147 | 148 | int main(void) { 149 | UNITY_BEGIN(); 150 | RUN_TEST(test_kw); 151 | RUN_TEST(test_kw_cmt); 152 | RUN_TEST(test_kw_nl_cmt); 153 | RUN_TEST(test_kw_cmt_nl2_cmt); 154 | RUN_TEST(test_kw_nl_cmt_nl_cmt); 155 | RUN_TEST(test_kw_nl2_cmt_nl_cmt); 156 | return UNITY_END(); 157 | } 158 | -------------------------------------------------------------------------------- /test/unit/parser/lex_misc.c: -------------------------------------------------------------------------------- 1 | #include "utarray.h" 2 | #include "utstring.h" 3 | 4 | #include "unity.h" 5 | #include "lex_misc.h" 6 | 7 | UT_string *buf; 8 | UT_string *test_s; 9 | UT_array *result; 10 | 11 | LOCAL const int tk[42] = { 12 | TK_STARSTAR, TK_ARROW, 13 | TK_LE, TK_GE, 14 | TK_SEMI, TK_COLON, 15 | TK_BANG_EQ, TK_BANG, 16 | TK_PLUS_EQ, TK_PLUS, /* 10 */ 17 | TK_MINUS_EQ, TK_MINUS, 18 | TK_STAR_EQ, TK_STAR, 19 | TK_DIVDIV_EQ, TK_DIVDIV, 20 | TK_DIV_EQ, TK_SLASH, 21 | TK_PCT_EQ, TK_PCT, /* 20 */ 22 | TK_AMP_EQ, TK_AMP, 23 | TK_VBAR_EQ, TK_VBAR, 24 | TK_CARET_EQ, TK_CARET, 25 | TK_LBRACK, TK_RBRACK, 26 | TK_LBRACE, TK_RBRACE, /* 30 */ 27 | TK_LPAREN, TK_RPAREN, 28 | TK_TILDE, 29 | 30 | TK_LLANGLE_EQ, TK_LLANGLE, TK_LANGLE, 31 | TK_RRANGLE_EQ, TK_RRANGLE, TK_RANGLE, 32 | TK_EQEQ, TK_EQ, 33 | TK_ESC_BACKSLASH /* 42 */ 34 | }; 35 | 36 | void setUp(void) { 37 | utstring_new(test_s); 38 | utstring_new(buf); 39 | } 40 | 41 | void tearDown(void) { 42 | utstring_free(test_s); 43 | utstring_free(buf); 44 | } 45 | 46 | void test_p(void) { 47 | for (int i=0; i < 42; i++) { 48 | printf("punct %s: :]%s[:\n", 49 | token_name[tk[i]][0], token_name[tk[i]][1]); 50 | utstring_renew(test_s); 51 | utstring_printf(test_s, "%s%s", 52 | token_name[tk[i]][1], 53 | " #cmt1\n #cmt2\n"); 54 | result = sealark_lex_string(utstring_body(test_s)); 55 | utstring_renew(buf); 56 | sealark_nodelist2string(result, buf); 57 | /* printf(utstring_body(buf)); */ 58 | TEST_ASSERT_EQUAL_STRING(utstring_body(test_s), utstring_body(buf)); 59 | utarray_free(result); 60 | } 61 | } 62 | 63 | int main(void) { 64 | UNITY_BEGIN(); 65 | /* RUN_TEST(test_punctuation); */ 66 | RUN_TEST(test_p); 67 | return UNITY_END(); 68 | } 69 | -------------------------------------------------------------------------------- /test/unit/parser/lex_punctuation.c: -------------------------------------------------------------------------------- 1 | #include "utarray.h" 2 | #include "utstring.h" 3 | #include "unity.h" 4 | #include "sealark.h" 5 | 6 | #include "lex_punctuation.h" 7 | 8 | UT_string *buf; 9 | UT_string *test_s; 10 | UT_array *result; 11 | 12 | LOCAL const int tk[42] = { 13 | TK_STAR2, TK_ARROW, 14 | TK_LE, TK_GE, 15 | TK_SEMI, TK_COLON, 16 | TK_BANG_EQ, TK_BANG, 17 | TK_PLUS_EQ, TK_PLUS, /* 10 */ 18 | TK_MINUS_EQ, TK_MINUS, 19 | TK_STAR_EQ, TK_STAR, 20 | TK_SLASH2_EQ, TK_SLASH2, 21 | TK_SLASH_EQ, TK_SLASH, 22 | TK_PCT_EQ, TK_PCT, /* 20 */ 23 | TK_AMP_EQ, TK_AMP, 24 | TK_VBAR_EQ, TK_VBAR, 25 | TK_CARET_EQ, TK_CARET, 26 | TK_LBRACK, TK_RBRACK, 27 | TK_LBRACE, TK_RBRACE, /* 30 */ 28 | TK_LPAREN, TK_RPAREN, 29 | TK_TILDE, 30 | 31 | TK_LLANGLE_EQ, TK_LLANGLE, TK_LANGLE, 32 | TK_RRANGLE_EQ, TK_RRANGLE, TK_RANGLE, 33 | TK_EQ2, TK_EQ, 34 | TK_BACKSLASH2 /* 42 */ 35 | }; 36 | 37 | void setUp(void) { 38 | utstring_new(test_s); 39 | utstring_new(buf); 40 | } 41 | 42 | void tearDown(void) { 43 | utstring_free(test_s); 44 | utstring_free(buf); 45 | } 46 | 47 | void test_p(void) { 48 | for (int i=0; i < 42; i++) { 49 | printf("punct %s: :]%s[:\n", 50 | token_name[tk[i]][0], token_name[tk[i]][1]); 51 | utstring_renew(test_s); 52 | utstring_printf(test_s, "%s%s", 53 | token_name[tk[i]][1], 54 | " #cmt1\n #cmt2\n"); 55 | result = sealark_lex_string(utstring_body(test_s)); 56 | utstring_renew(buf); 57 | sealark_nodelist2string(result, buf); 58 | /* printf(utstring_body(buf)); */ 59 | TEST_ASSERT_EQUAL_STRING(utstring_body(test_s), utstring_body(buf)); 60 | utarray_free(result); 61 | } 62 | } 63 | 64 | int main(void) { 65 | UNITY_BEGIN(); 66 | /* RUN_TEST(test_punctuation); */ 67 | RUN_TEST(test_p); 68 | return UNITY_END(); 69 | } 70 | -------------------------------------------------------------------------------- /test/unit/parser/syntax_call_expr.c: -------------------------------------------------------------------------------- 1 | #include "log.h" 2 | #include "utarray.h" 3 | #include "unity.h" 4 | #include "sealark.h" 5 | 6 | #include "syntax_call_expr.h" 7 | 8 | UT_string *buf; 9 | LOCAL char *test_str; 10 | struct node_s *root; 11 | 12 | LOCAL char *call_a[] = { 13 | "foo()\n", 14 | "foo(a)\n", 15 | "foo(a, b)\n", 16 | "foo(3)\n", 17 | "foo(3.14)\n", 18 | "foo(1.2e3)\n", 19 | "foo(1,2,3)\n", 20 | "foo(1.1, 2.2, 3.3)\n", 21 | "foo(a,1,b,2)\n", 22 | "foo( a , 1 , b , 2 )\n", 23 | "foo(a, bar(1), baz(1.2))\n", 24 | "foo(bar[:])\n", 25 | "foo(bar[f:g()])\n", 26 | /* optional trailing comma */ 27 | "foo(a,)\n", 28 | "foo(3,)\n", 29 | "foo(3.14,)\n", 30 | "foo(1.2e3,)\n", 31 | "foo(1,2,3,)\n", 32 | "foo(1.1, 2.2, 3.3,)\n", 33 | "foo(a,1,b,2,)\n", 34 | "foo( a , 1 , b , 2 , )\n", 35 | "foo(a, bar(1), baz(1.2) ,)\n", 36 | "foo(bar[:],)\n", 37 | "foo(bar[f:g()],)\n", 38 | NULL 39 | }; 40 | 41 | LOCAL char *call_rules[] = { 42 | "foo(a='b')\n", 43 | 44 | "ocaml_module(\n" 45 | " name = \"Uri\",\n" 46 | " struct = \"uri.ml\",\n" 47 | " sig = \"Uri.cmi\",\n" 48 | " deps = [\n" 49 | " \"@opam//lib/angstrom\",\n" 50 | " \"@opam//lib/stringext\",\n" 51 | " \"@opam//lib/yojson\",\n" 52 | " ]\n" 53 | ")\n", 54 | NULL 55 | }; 56 | 57 | void setUp(void) { 58 | utstring_new(buf); 59 | } 60 | 61 | void tearDown(void) { 62 | utstring_free(buf); 63 | } 64 | 65 | void test_call_a(void) { 66 | int ct; 67 | for (ct=0; call_a[ct] != NULL; ct++); 68 | for (int i=0; i < ct; i++) { 69 | /* printf("case %d: :]%s[:\n", i, call_a[i]); */ 70 | test_str = call_a[i]; 71 | root = sealark_parse_string(test_str); 72 | utstring_renew(buf); 73 | sealark_node_to_starlark(root, buf); 74 | /* printf(":]%s[:\n", utstring_body(buf)); */ 75 | TEST_ASSERT_EQUAL_STRING(test_str, utstring_body(buf)); 76 | sealark_node_free(root); 77 | } 78 | } 79 | 80 | void test_call_rules(void) { 81 | int ct; 82 | for (ct=0; call_rules[ct] != NULL; ct++); 83 | for (int i=0; i < ct; i++) { 84 | /* printf("case %d: :]%s[:\n", i, call_rules[i]); */ 85 | test_str = call_rules[i]; 86 | root = sealark_parse_string(test_str); 87 | utstring_renew(buf); 88 | sealark_node_to_starlark(root, buf); 89 | /* printf(":]%s[:\n", utstring_body(buf)); */ 90 | TEST_ASSERT_EQUAL_STRING(test_str, utstring_body(buf)); 91 | sealark_node_free(root); 92 | } 93 | } 94 | 95 | int main(void) { 96 | UNITY_BEGIN(); 97 | RUN_TEST(test_call_a); 98 | /* RUN_TEST(test_call_rules); */ 99 | return UNITY_END(); 100 | } 101 | -------------------------------------------------------------------------------- /test/unit/parser/syntax_dict.c: -------------------------------------------------------------------------------- 1 | #include "log.h" 2 | #include "utarray.h" 3 | #include "unity.h" 4 | #include "sealark.h" 5 | 6 | #include "syntax_dict.h" 7 | 8 | UT_string *buf; 9 | LOCAL char *test_str; 10 | struct node_s *root; 11 | 12 | LOCAL char *dict_comp[] = { 13 | "{x: len(x) for x in words}\n", 14 | "{x: x*2 for x in [1, 2]}\n", 15 | "{x: x*2 for x in f(a)}\n", 16 | "{x: x*2 for x in f(a[3:15:2])}\n", 17 | NULL 18 | }; 19 | 20 | LOCAL char *dict_expr[] = { 21 | "{a: b}\n", 22 | NULL 23 | }; 24 | 25 | void setUp(void) { 26 | utstring_new(buf); 27 | } 28 | 29 | void tearDown(void) { 30 | utstring_free(buf); 31 | } 32 | 33 | void test_dict_comp(void) { 34 | int ct; 35 | for (ct=0; dict_comp[ct] != NULL; ct++); 36 | for (int i=0; i < ct; i++) { 37 | /* printf("case %d: :]%s[:\n", i, dict_comp[i]); */ 38 | test_str = dict_comp[i]; 39 | root = sealark_parse_string(test_str); 40 | utstring_renew(buf); 41 | sealark_node_to_starlark(root, buf); 42 | /* printf(":]%s[:\n", utstring_body(buf)); */ 43 | TEST_ASSERT_EQUAL_STRING(test_str, utstring_body(buf)); 44 | sealark_node_free(root); 45 | } 46 | } 47 | 48 | void test_dict_expr(void) { 49 | int ct; 50 | for (ct=0; dict_expr[ct] != NULL; ct++); 51 | for (int i=0; i < ct; i++) { 52 | /* printf("case %d: :]%s[:\n", i, dict_expr[i]); */ 53 | test_str = dict_expr[i]; 54 | root = sealark_parse_string(test_str); 55 | utstring_renew(buf); 56 | sealark_node_to_starlark(root, buf); 57 | /* printf(":]%s[:\n", utstring_body(buf)); */ 58 | TEST_ASSERT_EQUAL_STRING(test_str, utstring_body(buf)); 59 | sealark_node_free(root); 60 | } 61 | } 62 | 63 | int main(void) { 64 | UNITY_BEGIN(); 65 | RUN_TEST(test_dict_comp); 66 | /* RUN_TEST(test_dict_expr); */ 67 | return UNITY_END(); 68 | } 69 | -------------------------------------------------------------------------------- /test/unit/parser/syntax_expressions.c: -------------------------------------------------------------------------------- 1 | #include "log.h" 2 | #include "utarray.h" 3 | #include "unity.h" 4 | #include "sealark.h" 5 | 6 | #include "syntax_expressions.h" 7 | 8 | UT_string *buf; 9 | LOCAL char *test_str; 10 | struct node_s *root; 11 | 12 | LOCAL char *if_expr[] = { 13 | "\"yes\" if enabled else \"no\"\n", 14 | "a if enabled else b\n", 15 | "a if b else (c if d else e)\n", 16 | "(a if b else c) if d else e\n", 17 | "lambda: (a if b else c)\n", 18 | "(lambda: a) if b else c\n", 19 | "a if b else lambda: (c if d else e)\n", 20 | "a if b else (lambda: c if d else e)\n", 21 | "(a if b else lambda: c) if d else e\n", 22 | NULL 23 | }; 24 | 25 | LOCAL char *paren_expr[] = { 26 | "a * (b + c)\n", 27 | "1 + 2 * 3 + 4\n", 28 | "(1 + 2) * (3 + 4)\n", 29 | NULL 30 | }; 31 | 32 | LOCAL char *dot_expr[] = { 33 | "a.b\n", 34 | "a.b.c\n", 35 | NULL 36 | }; 37 | 38 | LOCAL char *lambda[] = { 39 | "lambda x: x\n", 40 | "lambda x: 2*x\n", 41 | "map(lambda x: 2*x, range(3))\n", 42 | "map(lambda x: (2+x)*(3+x), range(3))\n", 43 | "lambda: (a if b else c)\n", 44 | "(lambda: a) if b else c\n", 45 | NULL 46 | }; 47 | 48 | void setUp(void) { 49 | utstring_new(buf); 50 | } 51 | 52 | void tearDown(void) { 53 | utstring_free(buf); 54 | } 55 | 56 | void test_if_expr(void) { 57 | int ct; 58 | for (ct=0; if_expr[ct] != NULL; ct++); 59 | for (int i=0; i < ct; i++) { 60 | /* printf("case %d: :]%s[:\n", i, if_expr[i]); */ 61 | test_str = if_expr[i]; 62 | root = sealark_parse_string(test_str); 63 | utstring_renew(buf); 64 | sealark_node_to_starlark(root, buf); 65 | /* printf(":]%s[:\n", utstring_body(buf)); */ 66 | TEST_ASSERT_EQUAL_STRING(test_str, utstring_body(buf)); 67 | sealark_node_free(root); 68 | } 69 | } 70 | 71 | void test_lambda(void) { 72 | int ct; 73 | for (ct=0; lambda[ct] != NULL; ct++); 74 | for (int i=0; i < ct; i++) { 75 | /* printf("case %d: :]%s[:\n", i, lambda[i]); */ 76 | test_str = lambda[i]; 77 | root = sealark_parse_string(test_str); 78 | utstring_renew(buf); 79 | sealark_node_to_starlark(root, buf); 80 | /* printf(":]%s[:\n", utstring_body(buf)); */ 81 | TEST_ASSERT_EQUAL_STRING(test_str, utstring_body(buf)); 82 | sealark_node_free(root); 83 | } 84 | } 85 | 86 | void test_paren_expr(void) { 87 | int ct; 88 | for (ct=0; paren_expr[ct] != NULL; ct++); 89 | for (int i=0; i < ct; i++) { 90 | /* printf("case %d: :]%s[:\n", i, paren_expr[i]); */ 91 | test_str = paren_expr[i]; 92 | root = sealark_parse_string(test_str); 93 | utstring_renew(buf); 94 | sealark_node_to_starlark(root, buf); 95 | /* printf(":]%s[:\n", utstring_body(buf)); */ 96 | TEST_ASSERT_EQUAL_STRING(test_str, utstring_body(buf)); 97 | sealark_node_free(root); 98 | } 99 | } 100 | 101 | void test_dot_expr(void) { 102 | int ct; 103 | for (ct=0; dot_expr[ct] != NULL; ct++); 104 | for (int i=0; i < ct; i++) { 105 | /* printf("case %d: :]%s[:\n", i, dot_expr[i]); */ 106 | test_str = dot_expr[i]; 107 | root = sealark_parse_string(test_str); 108 | utstring_renew(buf); 109 | sealark_node_to_starlark(root, buf); 110 | /* printf(":]%s[:\n", utstring_body(buf)); */ 111 | TEST_ASSERT_EQUAL_STRING(test_str, utstring_body(buf)); 112 | sealark_node_free(root); 113 | } 114 | } 115 | 116 | int main(void) { 117 | UNITY_BEGIN(); 118 | RUN_TEST(test_if_expr); 119 | RUN_TEST(test_lambda); 120 | RUN_TEST(test_paren_expr); 121 | RUN_TEST(test_dot_expr); 122 | return UNITY_END(); 123 | } 124 | -------------------------------------------------------------------------------- /test/unit/parser/syntax_lists.c: -------------------------------------------------------------------------------- 1 | #include "log.h" 2 | #include "utarray.h" 3 | #include "unity.h" 4 | #include "sealark.h" 5 | 6 | #include "syntax_lists.h" 7 | 8 | UT_string *buf; 9 | LOCAL char *test_str; 10 | struct node_s *root; 11 | 12 | LOCAL char *list_expr[] = { 13 | "[a]\n", 14 | "[a, b]\n", 15 | "[1, 2]\n", 16 | "[a, 2]\n", 17 | 18 | "[a, f()]\n", 19 | NULL 20 | }; 21 | 22 | LOCAL char *list_comp[] = { 23 | "[x*x for x in range(5)]\n", 24 | "[x*x for x in range(5) if x%2 == 0]\n", 25 | "[x*y+z for (x, y), z in [((2, 3), 5), ((\"o\", 2), \"!\")]]\n", 26 | "[x for x in range(5)\n" 27 | " if x%2 == 0]\n", 28 | 29 | "[x for x in range(5)\n" 30 | " for y in range(6)\n" 31 | " for z in range(7)]\n", 32 | 33 | "[x for x in range(5)\n" 34 | " if x%2 == 0\n" 35 | " for y in range(6)]\n", 36 | 37 | "[x for x in range(5)\n" 38 | " if x%2 == 0\n" 39 | " for y in range(5)\n" 40 | " if y > x]\n", 41 | 42 | NULL 43 | }; 44 | 45 | void setUp(void) { 46 | utstring_new(buf); 47 | } 48 | 49 | void tearDown(void) { 50 | utstring_free(buf); 51 | } 52 | 53 | void test_list_comp(void) { 54 | int ct; 55 | for (ct=0; list_comp[ct] != NULL; ct++); 56 | for (int i=0; i < ct; i++) { 57 | /* printf("case %d: :]%s[:\n", i, list_comp[i]); */ 58 | test_str = list_comp[i]; 59 | root = sealark_parse_string(test_str); 60 | utstring_renew(buf); 61 | sealark_node_to_starlark(root, buf); 62 | /* printf(":]%s[:\n", utstring_body(buf)); */ 63 | TEST_ASSERT_EQUAL_STRING(test_str, utstring_body(buf)); 64 | sealark_node_free(root); 65 | } 66 | } 67 | 68 | void test_list_expr(void) { 69 | int ct; 70 | for (ct=0; list_expr[ct] != NULL; ct++); 71 | for (int i=0; i < ct; i++) { 72 | /* printf("case %d: :]%s[:\n", i, list_expr[i]); */ 73 | test_str = list_expr[i]; 74 | root = sealark_parse_string(test_str); 75 | utstring_renew(buf); 76 | sealark_node_to_starlark(root, buf); 77 | /* printf(":]%s[:\n", utstring_body(buf)); */ 78 | TEST_ASSERT_EQUAL_STRING(test_str, utstring_body(buf)); 79 | sealark_node_free(root); 80 | } 81 | } 82 | 83 | int main(void) { 84 | UNITY_BEGIN(); 85 | RUN_TEST(test_list_expr); 86 | RUN_TEST(test_list_comp); 87 | return UNITY_END(); 88 | } 89 | -------------------------------------------------------------------------------- /test/unit/parser/syntax_slices.c: -------------------------------------------------------------------------------- 1 | #include "log.h" 2 | #include "utarray.h" 3 | #include "unity.h" 4 | #include "sealark.h" 5 | 6 | #include "syntax_slices.h" 7 | 8 | UT_string *buf; 9 | LOCAL char *test_str; 10 | struct node_s *root; 11 | 12 | LOCAL char *slice_a[] = { 13 | "foo[]\n", 14 | "foo[:]\n", 15 | "foo[::]\n", 16 | "foo[a]\n", 17 | "foo[a:]\n", 18 | "foo[a::]\n", 19 | "foo[a:b]\n", 20 | "foo[a:b:]\n", 21 | "foo[a::c]\n", 22 | "foo[a:b:c]\n", 23 | "foo[:b]\n", 24 | "foo[:b:]\n", 25 | "foo[:b:c]\n", 26 | "foo[::c]\n", 27 | NULL 28 | }; 29 | 30 | LOCAL char *slice_embed_a[] = { 31 | "foo[bar[]]\n", 32 | "foo[bar[:]]\n", 33 | "foo[bar[::]]\n", 34 | 35 | "foo[bar[]:]\n", 36 | "foo[bar[:]::]\n", 37 | 38 | "foo[bar[]:b]\n", 39 | "foo[bar[:]:b]\n", 40 | "foo[bar[::]:b]\n", 41 | 42 | "foo[bar[]:]\n", 43 | "foo[bar[]::]\n", 44 | "foo[bar[]:b]\n", 45 | "foo[bar[]:b:]\n", 46 | "foo[bar[]::c]\n", 47 | "foo[bar[]:b:c]\n", 48 | "foo[:b]\n", 49 | "foo[:b:]\n", 50 | "foo[:b:c]\n", 51 | "foo[::c]\n", 52 | 53 | "foo[bar(baz[])]\n", 54 | "foo[bar(baz[buz()])]\n", 55 | "foo[bar(baz[a])]\n", 56 | 57 | "foo[bar(baz[] #cmt\n)]\n", 58 | "foo[bar(baz[buz(a,1,2.0)])]\n", 59 | "foo[bar(\n baz[\n a\n]\n)\n]\n", 60 | NULL 61 | }; 62 | 63 | LOCAL char *slice_a_cmt[] = { 64 | "foo[] #cmt1\n", 65 | //FIXME "foo[] #cmt1\n\n\n\n", 66 | "foo[]\n #cmt1\n", 67 | "foo[]\n\n\n #cmt1\n", 68 | "foo[] #cmt1\n#cmt2\n", 69 | "foo[] #cmt1\n\n#cmt2\n", 70 | 71 | "foo[\n #cmt1\n]\n", 72 | "foo[\n #cmt1\n #cmt2\n]\n", 73 | "foo[\n\n #cmt1\n #cmt2\n]\n", 74 | "foo[\n\n #cmt1\n\n #cmt2\n]\n", 75 | "foo[\n\n #cmt1\n\n #cmt2\n\n]\n", 76 | "foo[\n #cmt1\n]\n #cmt2\n", 77 | 78 | "foo[:] #cmt1\n", 79 | "foo[ #cmt1\n:]\n", 80 | "foo[ #cmt1\n:\n#cmt2\n]\n", 81 | "foo[ #cmt1\n:\n#cmt2\n] #cmt3\n", 82 | 83 | "foo[::] #cmt1\n", 84 | "foo[ #cmt1\n::]\n", 85 | "foo[ #cmt1\n:: #cmt2\n]\n", 86 | "foo[ #cmt1\n: #cmt2\n:]\n", 87 | "foo[ #cmt1\n:\n #cmt2\n: #cmt3\n]\n", 88 | 89 | "foo[a] #cmt1\n", 90 | "foo[a:] #cmt1\n", 91 | 92 | "foo[a::] #cmt1\n", 93 | "foo[a #cmt1\n ::] #cmt2\n", 94 | "foo[a:: #cmt1\n]\n", 95 | "foo[\n #cmt1\na::\n #cmt2\n] #cmt3\n", 96 | 97 | "foo[a:b] #cmt1\n", 98 | "foo[a:b:] #cmt1\n", 99 | "foo[a::c] #cmt1\n", 100 | 101 | "foo[a:b:c] #cmt1\n", 102 | "foo[a #cmt1\n:b #cmt2\n:c #cmt3\n] #cmt4\n", 103 | "foo[ #cmt1\a:b:c #cmt2\n] #cmt3\n", 104 | "foo[a: #cmt1\nb: #cmt2\nc] #cmt1\n", 105 | 106 | "foo[:b] #cmt1\n", 107 | "foo[:b:] #cmt1\n", 108 | "foo[:b:c] #cmt1\n", 109 | "foo[::c] #cmt1\n", 110 | NULL 111 | }; 112 | 113 | LOCAL char *slice_int[] = { 114 | "foo[1]\n", 115 | "foo[1:]\n", 116 | "foo[1::]\n", 117 | "foo[1:2]\n", 118 | "foo[1:2:]\n", 119 | "foo[1::3]\n", 120 | "foo[1:2:3]\n", 121 | "foo[:2]\n", 122 | "foo[:2:]\n", 123 | "foo[:2:3]\n", 124 | "foo[::3]\n", 125 | NULL 126 | }; 127 | 128 | LOCAL char *slice_a_int[] = { 129 | "foo[1:a]\n", 130 | "foo[1:a:]\n", 131 | "foo[a:1]\n", 132 | "foo[a:1:]\n", 133 | "foo[a::3]\n", 134 | "foo[1::c]\n", 135 | "foo[a:2:3]\n", 136 | "foo[1:b:3]\n", 137 | "foo[1:2:c]\n", 138 | "foo[:b:3]\n", 139 | "foo[:2:c]\n", 140 | NULL 141 | }; 142 | 143 | LOCAL char *slice_float[] = { 144 | "foo[1.]\n", 145 | "foo[1.:]\n", 146 | "foo[1.::]\n", 147 | "foo[1.:2.]\n", 148 | "foo[1.:2.:]\n", 149 | "foo[1.::3.]\n", 150 | "foo[1.:2.:3.]\n", 151 | "foo[:2.]\n", 152 | "foo[:2.:]\n", 153 | "foo[:2.:3.]\n", 154 | "foo[::3.]\n", 155 | 156 | "foo[1.0]\n", 157 | "foo[1.0:]\n", 158 | "foo[1.0::]\n", 159 | "foo[1.0:2.0]\n", 160 | "foo[1.0:2.0:]\n", 161 | "foo[1.0::3.0]\n", 162 | "foo[1.0:2.0:3.0]\n", 163 | "foo[:2.0]\n", 164 | "foo[:2.0:]\n", 165 | "foo[:2.0:3.0]\n", 166 | "foo[::3.0]\n", 167 | 168 | "foo[1.9e123]\n", 169 | "foo[1.9e123:]\n", 170 | "foo[1.9e123::]\n", 171 | "foo[1.9e123:2.9e123]\n", 172 | "foo[1.9e123:2.9e123:]\n", 173 | "foo[1.9e123::3.9e123]\n", 174 | "foo[1.9e123:2.9e123:3.9e123]\n", 175 | "foo[:2.9e123]\n", 176 | "foo[:2.9e123:]\n", 177 | "foo[:2.9e123:3.9e123]\n", 178 | "foo[::3.9e123]\n", 179 | NULL 180 | }; 181 | 182 | LOCAL char *slice_a_float[] = { 183 | "foo[a:2.]\n", 184 | "foo[a:2.:]\n", 185 | "foo[a::3.]\n", 186 | "foo[a:2.:3.]\n", 187 | "foo[:b:3.]\n", 188 | "foo[::3.]\n", 189 | 190 | "foo[1.0:b]\n", 191 | "foo[1.0:b:]\n", 192 | "foo[1.0::3.0]\n", 193 | "foo[1.0:b:3.0]\n", 194 | "foo[:b]\n", 195 | "foo[:b:]\n", 196 | "foo[:b:3.0]\n", 197 | "foo[::3.0]\n", 198 | 199 | "foo[1.9e123]\n", 200 | "foo[1.9e123:]\n", 201 | "foo[1.9e123::]\n", 202 | "foo[1.9e123:2.9e123]\n", 203 | "foo[1.9e123:2.9e123:]\n", 204 | "foo[1.9e123::3.9e123]\n", 205 | "foo[1.9e123:2.9e123:3.9e123]\n", 206 | "foo[:2.9e123]\n", 207 | "foo[:2.9e123:]\n", 208 | "foo[:2.9e123:3.9e123]\n", 209 | "foo[::3.9e123]\n", 210 | NULL 211 | }; 212 | 213 | LOCAL char *slice_fn[] = { 214 | "foo[f()]\n", 215 | "foo[f(a)]\n", 216 | "foo[f(1)]\n", 217 | "foo[f(a,1)]\n", 218 | "foo[f(a,1.0)]\n", 219 | 220 | "foo[f():]\n", 221 | "foo[f(a):]\n", 222 | "foo[f(1):]\n", 223 | "foo[f(a,1):]\n", 224 | "foo[f(a,1.0):]\n", 225 | 226 | "foo[f()::]\n", 227 | "foo[f(a)::]\n", 228 | "foo[f(1)::]\n", 229 | "foo[f(a,1)::]\n", 230 | "foo[f(a,1.0)::]\n", 231 | 232 | "foo[f():g()]\n", 233 | "foo[f(a):g()]\n", 234 | "foo[f(1):g()]\n", 235 | "foo[f(a,1):g()]\n", 236 | "foo[f(a,1.0):g()]\n", 237 | 238 | "foo[f():g():]\n", 239 | "foo[f(a):g():]\n", 240 | "foo[f(1):g():]\n", 241 | "foo[f(a,1):g():]\n", 242 | "foo[f(a,1.0):g():]\n", 243 | 244 | "foo[f():g():h()]\n", 245 | "foo[f(a):g():h()]\n", 246 | "foo[f(1):g():h()]\n", 247 | "foo[f(a,1):g():h()]\n", 248 | "foo[f(a,1.0):g():h()]\n", 249 | 250 | "foo[f():g(b):h(c)]\n", 251 | "foo[f(a):g(b):h(c)]\n", 252 | "foo[f(1):g(b):h(c)]\n", 253 | "foo[f(a,1):g(b):h(c)]\n", 254 | "foo[f(a,1.0):g(b):h(c)]\n", 255 | NULL 256 | }; 257 | 258 | void setUp(void) { 259 | utstring_new(buf); 260 | } 261 | 262 | void tearDown(void) { 263 | utstring_free(buf); 264 | } 265 | 266 | void test_slice_a(void) { 267 | int ct; 268 | for (ct=0; slice_a[ct] != NULL; ct++); 269 | for (int i=0; i < ct; i++) { 270 | /* printf("case %d: :]%s[:\n", i, slice_a[i]); */ 271 | test_str = slice_a[i]; 272 | root = sealark_parse_string(test_str); 273 | utstring_renew(buf); 274 | sealark_node_to_starlark(root, buf); 275 | /* printf(":]%s[:\n", utstring_body(buf)); */ 276 | TEST_ASSERT_EQUAL_STRING(test_str, utstring_body(buf)); 277 | sealark_node_free(root); 278 | } 279 | } 280 | 281 | void test_slice_embed_a(void) { 282 | int ct; 283 | for (ct=0; slice_embed_a[ct] != NULL; ct++); 284 | for (int i=0; i < ct; i++) { 285 | /* printf("case %d: :]%s[:\n", i, slice_embed_a[i]); */ 286 | test_str = slice_embed_a[i]; 287 | root = sealark_parse_string(test_str); 288 | utstring_renew(buf); 289 | sealark_node_to_starlark(root, buf); 290 | /* printf(":]%s[:\n", utstring_body(buf)); */ 291 | TEST_ASSERT_EQUAL_STRING(test_str, utstring_body(buf)); 292 | sealark_node_free(root); 293 | } 294 | } 295 | 296 | void test_slice_a_cmt(void) { 297 | int ct; 298 | for (ct=0; slice_a_cmt[ct] != NULL; ct++); 299 | for (int i=0; i < ct; i++) { 300 | /* printf("case %d: :]%s[:\n", i, slice_a_cmt[i]); */ 301 | test_str = slice_a_cmt[i]; 302 | root = sealark_parse_string(test_str); 303 | utstring_renew(buf); 304 | sealark_node_to_starlark(root, buf); 305 | /* printf(":]%s[:\n", utstring_body(buf)); */ 306 | TEST_ASSERT_EQUAL_STRING(test_str, utstring_body(buf)); 307 | sealark_node_free(root); 308 | } 309 | } 310 | 311 | void test_slice_int(void) { 312 | int ct; 313 | for (ct=0; slice_int[ct] != NULL; ct++); 314 | for (int i=0; i < ct; i++) { 315 | // printf("case %d: :]%s[:\n", i, slice_int[i]); 316 | test_str = slice_int[i]; 317 | root = sealark_parse_string(test_str); 318 | utstring_renew(buf); 319 | sealark_node_to_starlark(root, buf); 320 | // printf(":]%s[:\n", utstring_body(buf)); 321 | TEST_ASSERT_EQUAL_STRING(test_str, utstring_body(buf)); 322 | sealark_node_free(root); 323 | } 324 | } 325 | 326 | void test_slice_float(void) { 327 | int ct; 328 | for (ct=0; slice_float[ct] != NULL; ct++); 329 | for (int i=0; i < ct; i++) { 330 | // printf("case %d: :]%s[:\n", i, slice_float[i]); 331 | test_str = slice_float[i]; 332 | root = sealark_parse_string(test_str); 333 | utstring_renew(buf); 334 | sealark_node_to_starlark(root, buf); 335 | // printf(":]%s[:\n", utstring_body(buf)); 336 | TEST_ASSERT_EQUAL_STRING(test_str, utstring_body(buf)); 337 | sealark_node_free(root); 338 | } 339 | } 340 | 341 | void test_slice_a_float(void) { 342 | int ct; 343 | for (ct=0; slice_a_float[ct] != NULL; ct++); 344 | for (int i=0; i < ct; i++) { 345 | // printf("case %d: :]%s[:\n", i, slice_a_float[i]); 346 | test_str = slice_a_float[i]; 347 | root = sealark_parse_string(test_str); 348 | utstring_renew(buf); 349 | sealark_node_to_starlark(root, buf); 350 | // printf(":]%s[:\n", utstring_body(buf)); 351 | TEST_ASSERT_EQUAL_STRING(test_str, utstring_body(buf)); 352 | sealark_node_free(root); 353 | } 354 | } 355 | 356 | void test_slice_a_int(void) { 357 | int ct; 358 | for (ct=0; slice_a_int[ct] != NULL; ct++); 359 | for (int i=0; i < ct; i++) { 360 | // printf("case %d: :]%s[:\n", i, slice_a_int[i]); 361 | test_str = slice_a_int[i]; 362 | root = sealark_parse_string(test_str); 363 | utstring_renew(buf); 364 | sealark_node_to_starlark(root, buf); 365 | // printf(":]%s[:\n", utstring_body(buf)); 366 | TEST_ASSERT_EQUAL_STRING(test_str, utstring_body(buf)); 367 | sealark_node_free(root); 368 | } 369 | } 370 | 371 | void test_slice_fn(void) { 372 | int ct; 373 | for (ct=0; slice_fn[ct] != NULL; ct++); 374 | for (int i=0; i < ct; i++) { 375 | // printf("case %d: :]%s[:\n", i, slice_fn[i]); 376 | test_str = slice_fn[i]; 377 | root = sealark_parse_string(test_str); 378 | utstring_renew(buf); 379 | sealark_node_to_starlark(root, buf); 380 | // printf(":]%s[:\n", utstring_body(buf)); 381 | TEST_ASSERT_EQUAL_STRING(test_str, utstring_body(buf)); 382 | sealark_node_free(root); 383 | } 384 | } 385 | 386 | int main(void) { 387 | UNITY_BEGIN(); 388 | RUN_TEST(test_slice_a); 389 | RUN_TEST(test_slice_embed_a); 390 | RUN_TEST(test_slice_a_cmt); 391 | RUN_TEST(test_slice_int); 392 | RUN_TEST(test_slice_a_int); 393 | RUN_TEST(test_slice_float); 394 | RUN_TEST(test_slice_a_float); 395 | RUN_TEST(test_slice_fn); 396 | return UNITY_END(); 397 | } 398 | -------------------------------------------------------------------------------- /test/unit/parser/syntax_statements.c: -------------------------------------------------------------------------------- 1 | #include "log.h" 2 | #include "utarray.h" 3 | #include "unity.h" 4 | #include "sealark.h" 5 | 6 | #include "syntax_statements.h" 7 | 8 | UT_string *buf; 9 | LOCAL char *test_str; 10 | struct node_s *root; 11 | 12 | LOCAL char *def_stmts[] = { 13 | "def f(): pass\n", 14 | "def f(a, b, c): pass\n", 15 | "def f(a, b, c=1): pass\n", 16 | "def f(a, b, c=1, *args): pass\n", 17 | "def f(a, b, c=1, *args, **kwargs): pass\n", 18 | "def f(**kwargs): pass\n", 19 | 20 | "def list_to_dict(items):\n" 21 | " # Convert list of tuples to dict\n" 22 | " m = {}\n" 23 | " for k, m[k] in items:\n" 24 | " pass\n" 25 | " return m\n", 26 | 27 | "def list_to_dict(items):\n" 28 | " # Convert list of tuples to dict\n" 29 | " m = {}\n" 30 | " for k, m[k] in items: pass; return m\n", 31 | 32 | NULL 33 | }; 34 | 35 | LOCAL char *if_stmts[] = { 36 | "if x%2 == 1: continue\n", 37 | 38 | "if x%2 == 1:\n" 39 | " continue\n", 40 | 41 | "if x%2 == 1: # skip evens\n" 42 | " continue\n", 43 | 44 | "if x > 7: break\n", 45 | 46 | "if x > 7:\n" 47 | " break\n", 48 | 49 | "if x > 7: # stop at 8\n" 50 | " break\n", 51 | 52 | NULL 53 | }; 54 | 55 | LOCAL char *for_stmts[] = { 56 | "for a in [1, 2, 3]: print(a)\n", 57 | "for a, i in [[\"a\", 1], [\"b\", 2], [\"c\", 3]]: print(a, i)\n", 58 | NULL 59 | }; 60 | 61 | /* SimpleStmt = SmallStmt {';' SmallStmt} [';'] '\n' . */ 62 | /* SmallStmt = ReturnStmt */ 63 | /* | BreakStmt | ContinueStmt | PassStmt */ 64 | /* | AssignStmt */ 65 | /* | ExprStmt */ 66 | /* | LoadStmt */ 67 | 68 | LOCAL char *simple[] = { 69 | "return\n", 70 | "break\n", 71 | "continue\n", 72 | "pass\n", 73 | 74 | NULL 75 | }; 76 | 77 | LOCAL char *assignments[] = { 78 | "k = 1\n", 79 | "a[i] = v\n", 80 | "m.f = \"\"\n", 81 | "a, b = 2, 3\n", 82 | "(x, y) = f()\n", 83 | "[zero, one, two] = range(3)\n", 84 | "[] = ()\n", 85 | "[(a, b), (c, d)] = (\"ab\", \"cd\")\n", 86 | NULL 87 | }; 88 | 89 | LOCAL char *multi_assignments[] = { 90 | "a,b = c,d\n", 91 | "a,b = (c,d)\n", 92 | "a,b = (c,d,)\n", 93 | "(a, b), (c, d) = (\"ab\", \"cd\")\n", 94 | "(a, b), (c, d) = ('ab', 'cd'), (1, 2)\n", 95 | /* "a,b = c,\n", /\* illegal *\/ */ 96 | NULL 97 | }; 98 | 99 | LOCAL char *augmented_assignments[] = { 100 | "x += 1\n", 101 | "x -= 1\n", 102 | "x *= 1\n", 103 | "x /= 1\n", 104 | "x //= 1\n", 105 | "x %= 1\n", 106 | "x &= 1\n", 107 | "x |= 1\n", 108 | "x ^= 1\n", 109 | "x <<= 1\n", 110 | "x >>= 1\n", 111 | 112 | "x -= 1\n", 113 | "x = x - 1\n", 114 | 115 | "x.filename += \".sky\"\n", 116 | "x.filename = x.filename + \".sky\"\n", 117 | "a[index()] *= 2\n", 118 | 119 | "i = index()\n", 120 | "a[i] = b[j] * 2\n", 121 | 122 | NULL 123 | }; 124 | 125 | LOCAL char *load_stmts[] = { 126 | "load(\"module.sky\", \"x\", \"y\", \"z\")\n", 127 | /* # assigns x, y, and z */ 128 | "load(\"module.sky\", \"x\", y2=\"y\", \"z\")\n", 129 | /* # assigns x, y2, and z */ 130 | NULL 131 | }; 132 | 133 | void setUp(void) { 134 | utstring_new(buf); 135 | } 136 | 137 | void tearDown(void) { 138 | utstring_free(buf); 139 | } 140 | 141 | void test_simple(void) { 142 | int ct; 143 | for (ct=0; simple[ct] != NULL; ct++); 144 | for (int i=0; i < ct; i++) { 145 | /* printf("case %d: :]%s[:\n", i, simple[i]); */ 146 | test_str = simple[i]; 147 | root = sealark_parse_string(test_str); 148 | utstring_renew(buf); 149 | sealark_node_to_starlark(root, buf); 150 | /* printf(":]%s[:\n", utstring_body(buf)); */ 151 | TEST_ASSERT_EQUAL_STRING(test_str, utstring_body(buf)); 152 | sealark_node_free(root); 153 | } 154 | } 155 | 156 | void test_def_stmts(void) { 157 | int ct; 158 | for (ct=0; def_stmts[ct] != NULL; ct++); 159 | for (int i=0; i < ct; i++) { 160 | /* printf("case %d: :]%s[:\n", i, def_stmts[i]); */ 161 | test_str = def_stmts[i]; 162 | root = sealark_parse_string(test_str); 163 | utstring_renew(buf); 164 | sealark_node_to_starlark(root, buf); 165 | /* printf(":]%s[:\n", utstring_body(buf)); */ 166 | TEST_ASSERT_EQUAL_STRING(test_str, utstring_body(buf)); 167 | sealark_node_free(root); 168 | } 169 | } 170 | 171 | void test_if_stmts(void) { 172 | int ct; 173 | for (ct=0; if_stmts[ct] != NULL; ct++); 174 | for (int i=0; i < ct; i++) { 175 | /* printf("case %d: :]%s[:\n", i, if_stmts[i]); */ 176 | test_str = if_stmts[i]; 177 | root = sealark_parse_string(test_str); 178 | utstring_renew(buf); 179 | sealark_node_to_starlark(root, buf); 180 | /* printf(":]%s[:\n", utstring_body(buf)); */ 181 | TEST_ASSERT_EQUAL_STRING(test_str, utstring_body(buf)); 182 | sealark_node_free(root); 183 | } 184 | } 185 | 186 | void test_for_stmts(void) { 187 | int ct; 188 | for (ct=0; for_stmts[ct] != NULL; ct++); 189 | for (int i=0; i < ct; i++) { 190 | /* printf("case %d: :]%s[:\n", i, for_stmts[i]); */ 191 | test_str = for_stmts[i]; 192 | root = sealark_parse_string(test_str); 193 | utstring_renew(buf); 194 | sealark_node_to_starlark(root, buf); 195 | /* printf(":]%s[:\n", utstring_body(buf)); */ 196 | TEST_ASSERT_EQUAL_STRING(test_str, utstring_body(buf)); 197 | sealark_node_free(root); 198 | } 199 | } 200 | 201 | void test_assignments(void) { 202 | int ct; 203 | for (ct=0; assignments[ct] != NULL; ct++); 204 | for (int i=0; i < ct; i++) { 205 | /* printf("case %d: :]%s[:\n", i, assignments[i]); */ 206 | test_str = assignments[i]; 207 | root = sealark_parse_string(test_str); 208 | utstring_renew(buf); 209 | sealark_node_to_starlark(root, buf); 210 | /* printf(":]%s[:\n", utstring_body(buf)); */ 211 | TEST_ASSERT_EQUAL_STRING(test_str, utstring_body(buf)); 212 | sealark_node_free(root); 213 | } 214 | } 215 | 216 | void test_multi_assignments(void) { 217 | int ct; 218 | for (ct=0; multi_assignments[ct] != NULL; ct++); 219 | for (int i=0; i < ct; i++) { 220 | /* printf("case %d: :]%s[:\n", i, multi_assignments[i]); */ 221 | test_str = multi_assignments[i]; 222 | root = sealark_parse_string(test_str); 223 | utstring_renew(buf); 224 | sealark_node_to_starlark(root, buf); 225 | /* printf(":]%s[:\n", utstring_body(buf)); */ 226 | TEST_ASSERT_EQUAL_STRING(test_str, utstring_body(buf)); 227 | sealark_node_free(root); 228 | } 229 | } 230 | 231 | void test_augmented_assignments(void) { 232 | int ct; 233 | for (ct=0; augmented_assignments[ct] != NULL; ct++); 234 | for (int i=0; i < ct; i++) { 235 | /* printf("case %d: :]%s[:\n", i, augmented_assignments[i]); */ 236 | test_str = augmented_assignments[i]; 237 | root = sealark_parse_string(test_str); 238 | utstring_renew(buf); 239 | sealark_node_to_starlark(root, buf); 240 | /* printf(":]%s[:\n", utstring_body(buf)); */ 241 | TEST_ASSERT_EQUAL_STRING(test_str, utstring_body(buf)); 242 | sealark_node_free(root); 243 | } 244 | } 245 | 246 | void test_load_stmts(void) { 247 | int ct; 248 | for (ct=0; load_stmts[ct] != NULL; ct++); 249 | for (int i=0; i < ct; i++) { 250 | /* printf("case %d: :]%s[:\n", i, load_stmts[i]); */ 251 | test_str = load_stmts[i]; 252 | root = sealark_parse_string(test_str); 253 | utstring_renew(buf); 254 | sealark_node_to_starlark(root, buf); 255 | /* printf(":]%s[:\n", utstring_body(buf)); */ 256 | TEST_ASSERT_EQUAL_STRING(test_str, utstring_body(buf)); 257 | sealark_node_free(root); 258 | } 259 | } 260 | 261 | int main(void) { 262 | UNITY_BEGIN(); 263 | RUN_TEST(test_simple); 264 | RUN_TEST(test_def_stmts); 265 | RUN_TEST(test_if_stmts); 266 | RUN_TEST(test_for_stmts); 267 | RUN_TEST(test_assignments); 268 | RUN_TEST(test_multi_assignments); 269 | RUN_TEST(test_augmented_assignments); 270 | RUN_TEST(test_load_stmts); 271 | return UNITY_END(); 272 | } 273 | -------------------------------------------------------------------------------- /test/unit/sealark/BUILD.bazel: -------------------------------------------------------------------------------- 1 | load("@rules_cc//cc:defs.bzl", "cc_library") 2 | load("@makeheaders//src:RULES.bzl", "makeheaders") 3 | TOOLCHAINS = ["//:test_module_profiles"] 4 | 5 | test_suite( 6 | name = "sealark", 7 | tests = [ 8 | ]) 9 | 10 | cc_test( 11 | name = "buildfile_expressors", 12 | srcs = [ 13 | "buildfile_expressors.c", 14 | ":mkhdrs" 15 | ], 16 | data = [ 17 | "//test/data/cc:BUILD.test" 18 | ], 19 | copts = select({ 20 | "//bzl/host:macos": ["-std=c11"], 21 | "//bzl/host:linux": ["-std=gnu11"], 22 | "//conditions:default": ["-std=c11"], 23 | }) + [ 24 | "-pedantic-errors", 25 | 26 | "-I$(GENDIR)/$(@)/src", 27 | "-I$(GENDIR)/$(@)/test/unit/sealark", 28 | 29 | "-I$(@liblogc)/src", 30 | "-I$(@unity)/src", 31 | "-I$(@uthash)/src", 32 | ], 33 | linkstatic = 1, 34 | deps = [ 35 | "//src:sealark", 36 | "@liblogc//src:logc", 37 | "@unity//src:unity", 38 | "@uthash//src:uthash" 39 | ], 40 | timeout = "short", 41 | toolchains = TOOLCHAINS 42 | ) 43 | 44 | ################################################################ 45 | makeheaders( 46 | name = "mkhdrs", 47 | hdrs_srcs = [ 48 | "//src:sealark_debug.c", 49 | "buildfile_expressors.c", 50 | ], 51 | # outs = [ 52 | # "buildfile_expressors.h", 53 | # ], 54 | # cmd = "\n".join([ 55 | # "SRC1=$(location buildfile_expressors.c)", 56 | # "SRCDIR1=`dirname $$SRC1`", 57 | # "$(location //vendored/makeheaders) \\", 58 | # " $(location //sealark:debug.c) \\", 59 | # " $(location buildfile_expressors.c)", 60 | # "cp $${SRCDIR1}/*.h $(@D)", 61 | # ]), 62 | # tools = ["//vendored/makeheaders"], 63 | visibility = ["//visibility:public"] 64 | ) 65 | -------------------------------------------------------------------------------- /test/unit/sealark/buildfile_expressors.c: -------------------------------------------------------------------------------- 1 | #include "utarray.h" 2 | #include "utstring.h" 3 | #include "unity.h" 4 | #include "sealark.h" 5 | 6 | #include "buildfile_expressors.h" 7 | 8 | UT_string *buf; 9 | UT_string *test_s; 10 | UT_array *result; 11 | 12 | char *build_file = "test/data/cc/BUILD.test"; 13 | 14 | struct node_s *parse_state; 15 | 16 | struct node_s *ast; 17 | 18 | void setUp(void) { 19 | ast = sealark_parse_file(build_file); 20 | /* ast = parse_state->root; */ 21 | } 22 | 23 | void tearDown(void) { 24 | /* sealark_parse_state_free(parse_state); */ 25 | sealark_node_free(ast); 26 | } 27 | 28 | void test_target_for_index(void) { 29 | // (:targets 1 :bindings)) 30 | struct node_s *target = sealark_target_for_index(ast, 0); 31 | TEST_ASSERT_EQUAL_INT(4, sealark_target_bindings_count(target)); 32 | TEST_ASSERT_EQUAL_INT(target->tid, TK_Call_Expr); 33 | 34 | target = sealark_target_for_index(ast, 1); 35 | TEST_ASSERT_EQUAL_INT(3, sealark_target_bindings_count(target)); 36 | TEST_ASSERT_EQUAL_INT(target->tid, TK_Call_Expr); 37 | } 38 | 39 | int main(void) { 40 | UNITY_BEGIN(); 41 | RUN_TEST(test_target_for_index); 42 | return UNITY_END(); 43 | } 44 | --------------------------------------------------------------------------------