├── src
├── ast
│ └── nodes
│ │ └── _base.ts
├── cli
│ ├── index.ts
│ ├── ui
│ │ └── completions.ts
│ ├── commands
│ │ └── parse.ts
│ └── BaseCommand.ts
├── util
│ ├── logger.ts
│ ├── strings.ts
│ ├── paths.ts
│ ├── symbol-table.ts
│ ├── diagnostics.ts
│ ├── result.ts
│ └── position.ts
├── index.ts
├── grammar
│ ├── CWScriptLexer.tokens
│ └── CWScriptParser.tokens
└── parser
│ ├── index.ts
│ └── validation.ts
├── dist
├── ast
│ └── nodes
│ │ ├── _base.d.ts
│ │ ├── _base.js
│ │ └── _base.js.map
├── parser
│ ├── validation.d.ts
│ ├── index.d.ts
│ ├── validation.js.map
│ ├── index.js.map
│ ├── index.js
│ ├── visitor.d.ts
│ └── validation.js
├── util
│ ├── logger.d.ts
│ ├── logger.js
│ ├── logger.js.map
│ ├── strings.d.ts
│ ├── diagnostics.d.ts
│ ├── paths.d.ts
│ ├── paths.js.map
│ ├── strings.js.map
│ ├── strings.js
│ ├── symbol-table.d.ts
│ ├── result.d.ts
│ ├── symbol-table.js.map
│ ├── paths.js
│ ├── symbol-table.js
│ ├── diagnostics.js.map
│ ├── diagnostics.js
│ ├── result.js.map
│ ├── result.js
│ ├── position.d.ts
│ ├── position.js.map
│ └── position.js
├── cli
│ ├── index.d.ts
│ ├── ui
│ │ ├── completions.d.ts
│ │ ├── completions.js.map
│ │ └── completions.js
│ ├── index.js.map
│ ├── index.js
│ ├── commands
│ │ ├── parse.d.ts
│ │ ├── parse.js.map
│ │ └── parse.js
│ ├── BaseCommand.d.ts
│ ├── BaseCommand.js.map
│ └── BaseCommand.js
├── index.d.ts
├── grammar
│ ├── CWScriptParserVisitor.js.map
│ ├── CWScriptParserListener.js.map
│ ├── CWScriptParserListener.js
│ ├── CWScriptParserVisitor.js
│ └── CWScriptLexer.d.ts
├── bundle.node.js.LICENSE.txt
├── index.js.map
├── bundle.js.LICENSE.txt
├── index.js
└── interpreter.d.ts
├── .gitignore
├── bin
├── dev.cmd
├── run.cmd
├── run
└── dev
├── bun.lockb
├── jest.config.js
├── .vscode
├── settings.json
└── launch.json
├── .idea
├── codeStyles
│ ├── codeStyleConfig.xml
│ └── Project.xml
├── vcs.xml
├── misc.xml
├── .gitignore
├── prettier.xml
├── modules.xml
└── inspectionProfiles
│ └── Project_Default.xml
├── .swcrc
├── .github
└── workflows
│ ├── size.yml
│ └── main.yml
├── .editorconfig
├── examples
├── test-suite
│ ├── unit
│ │ └── 1_errors.cws
│ └── 999_kitchen_sink.cws
├── stdlib
│ └── stdlib.cws
├── cw-template
│ └── CWTemplate.cws
├── kitchen-sink
│ └── kitchen-sink.cws
├── test-contract
│ └── test-contract.cws
├── atomic-order-example
│ └── AtomicOrderExample.cws
└── terraswap
│ └── TerraswapFactory.cws
├── cwsc-x.iml
├── util
└── print-ast.ts
├── tsconfig.json
├── LICENSE.md
├── webpack.config.js
├── grammar
├── CWScriptLexer.g4
├── .antlr
│ ├── CWScriptLexer.tokens
│ └── CWScriptParser.tokens
├── CWScriptLexer.tokens
└── gen
│ └── CWScriptLexer.tokens
├── gen
└── CWScriptLexer.tokens
├── __tests__
└── interpreter
│ └── TerraswapToken.test.ts
├── oclif.manifest.json
├── package.json
├── scripts
└── generate-textmate.ts
└── README.md
/src/ast/nodes/_base.ts:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/dist/ast/nodes/_base.d.ts:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/dist/parser/validation.d.ts:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/dist/util/logger.d.ts:
--------------------------------------------------------------------------------
1 | export {};
2 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | node_modules
2 | .DS_Store
3 |
--------------------------------------------------------------------------------
/bin/dev.cmd:
--------------------------------------------------------------------------------
1 | @echo off
2 |
3 | node "%~dp0\dev" %*
--------------------------------------------------------------------------------
/src/cli/index.ts:
--------------------------------------------------------------------------------
1 | export {run} from '@oclif/core'
2 |
--------------------------------------------------------------------------------
/src/util/logger.ts:
--------------------------------------------------------------------------------
1 | import winston from 'winston';
2 |
--------------------------------------------------------------------------------
/bin/run.cmd:
--------------------------------------------------------------------------------
1 | @echo off
2 |
3 | node "%~dp0\run" %*
4 |
--------------------------------------------------------------------------------
/dist/cli/index.d.ts:
--------------------------------------------------------------------------------
1 | export { run } from '@oclif/core';
2 |
--------------------------------------------------------------------------------
/bun.lockb:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hyperweb-io/cwsc/HEAD/bun.lockb
--------------------------------------------------------------------------------
/dist/ast/nodes/_base.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 | //# sourceMappingURL=_base.js.map
--------------------------------------------------------------------------------
/jest.config.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | transform: {
3 | '^.+\\.(t|j)sx?$': '@swc/jest',
4 | },
5 | };
6 |
--------------------------------------------------------------------------------
/dist/cli/ui/completions.d.ts:
--------------------------------------------------------------------------------
1 | import omelette from 'omelette';
2 | export declare const completions: omelette.Instance;
3 |
--------------------------------------------------------------------------------
/.vscode/settings.json:
--------------------------------------------------------------------------------
1 | {
2 | "files.associations": {
3 | "*.ttml": "xml",
4 | "*.ttss": "css"
5 | }
6 | }
--------------------------------------------------------------------------------
/dist/util/logger.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 | Object.defineProperty(exports, "__esModule", { value: true });
3 | //# sourceMappingURL=logger.js.map
--------------------------------------------------------------------------------
/dist/util/logger.js.map:
--------------------------------------------------------------------------------
1 | {"version":3,"file":"logger.js","sourceRoot":"","sources":["../../src/util/logger.ts"],"names":[],"mappings":""}
--------------------------------------------------------------------------------
/dist/index.d.ts:
--------------------------------------------------------------------------------
1 | export { CWSParser } from './parser';
2 | export { CWSInterpreter } from './interpreter';
3 | export * as AST from './ast';
4 |
--------------------------------------------------------------------------------
/src/index.ts:
--------------------------------------------------------------------------------
1 | export { CWSParser } from './parser';
2 | export { CWSInterpreter } from './interpreter';
3 | export * as AST from './ast';
4 |
--------------------------------------------------------------------------------
/dist/ast/nodes/_base.js.map:
--------------------------------------------------------------------------------
1 | {"version":3,"file":"_base.js","sourceRoot":"","sources":["../../../src/ast/nodes/_base.ts"],"names":[],"mappings":""}
--------------------------------------------------------------------------------
/dist/util/strings.d.ts:
--------------------------------------------------------------------------------
1 | export declare function snakeToPascal(s: string): string;
2 | export declare function pascalToSnake(s: string): string;
3 |
--------------------------------------------------------------------------------
/dist/cli/index.js.map:
--------------------------------------------------------------------------------
1 | {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/cli/index.ts"],"names":[],"mappings":";;;AAAA,oCAA+B;AAAvB,2FAAA,GAAG,OAAA"}
--------------------------------------------------------------------------------
/bin/run:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env node
2 |
3 | const oclif = require('@oclif/core')
4 |
5 | oclif.run().then(require('@oclif/core/flush')).catch(require('@oclif/core/handle'))
6 |
--------------------------------------------------------------------------------
/.idea/codeStyles/codeStyleConfig.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/dist/grammar/CWScriptParserVisitor.js.map:
--------------------------------------------------------------------------------
1 | {"version":3,"file":"CWScriptParserVisitor.js","sourceRoot":"","sources":["../../src/grammar/CWScriptParserVisitor.ts"],"names":[],"mappings":";AAAA,qEAAqE"}
--------------------------------------------------------------------------------
/.idea/vcs.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/dist/grammar/CWScriptParserListener.js.map:
--------------------------------------------------------------------------------
1 | {"version":3,"file":"CWScriptParserListener.js","sourceRoot":"","sources":["../../src/grammar/CWScriptParserListener.ts"],"names":[],"mappings":";AAAA,qEAAqE"}
--------------------------------------------------------------------------------
/.idea/misc.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/.swcrc:
--------------------------------------------------------------------------------
1 | {
2 | "jsc": {
3 | "parser": {
4 | "syntax": "typescript"
5 | },
6 | "target": "es2017",
7 | },
8 | "module": {
9 | "type": "commonjs"
10 | },
11 | "sourceMaps": true
12 | }
--------------------------------------------------------------------------------
/dist/bundle.node.js.LICENSE.txt:
--------------------------------------------------------------------------------
1 | /*!
2 | * Copyright 2016 The ANTLR Project. All rights reserved.
3 | * Licensed under the BSD-3-Clause license. See LICENSE file in the project root for license information.
4 | */
5 |
--------------------------------------------------------------------------------
/.idea/.gitignore:
--------------------------------------------------------------------------------
1 | # Default ignored files
2 | /shelf/
3 | /workspace.xml
4 | # Editor-based HTTP Client requests
5 | /httpRequests/
6 | # Datasource local storage ignored files
7 | /dataSources/
8 | /dataSources.local.xml
9 |
--------------------------------------------------------------------------------
/dist/index.js.map:
--------------------------------------------------------------------------------
1 | {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;AAAA,mCAAqC;AAA5B,mGAAA,SAAS,OAAA;AAClB,6CAA+C;AAAtC,6GAAA,cAAc,OAAA;AACvB,6CAA6B"}
--------------------------------------------------------------------------------
/dist/grammar/CWScriptParserListener.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 | // Generated from ./grammar/CWScriptParser.g4 by ANTLR 4.9.0-SNAPSHOT
3 | Object.defineProperty(exports, "__esModule", { value: true });
4 | //# sourceMappingURL=CWScriptParserListener.js.map
--------------------------------------------------------------------------------
/dist/grammar/CWScriptParserVisitor.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 | // Generated from ./grammar/CWScriptParser.g4 by ANTLR 4.9.0-SNAPSHOT
3 | Object.defineProperty(exports, "__esModule", { value: true });
4 | //# sourceMappingURL=CWScriptParserVisitor.js.map
--------------------------------------------------------------------------------
/dist/util/diagnostics.d.ts:
--------------------------------------------------------------------------------
1 | import { TextView } from './position';
2 | import { Diagnostic } from 'vscode-languageserver';
3 | export declare function errorReportWithCodeSnippet(filename: string, sourceText: TextView, diagnostic: Diagnostic): string;
4 |
--------------------------------------------------------------------------------
/.idea/prettier.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
--------------------------------------------------------------------------------
/.idea/modules.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/dist/cli/index.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 | Object.defineProperty(exports, "__esModule", { value: true });
3 | exports.run = void 0;
4 | var core_1 = require("@oclif/core");
5 | Object.defineProperty(exports, "run", { enumerable: true, get: function () { return core_1.run; } });
6 | //# sourceMappingURL=index.js.map
--------------------------------------------------------------------------------
/.idea/inspectionProfiles/Project_Default.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/src/util/strings.ts:
--------------------------------------------------------------------------------
1 | export function snakeToPascal(s: string): string {
2 | return s
3 | .split('_')
4 | .map((x) => x[0].toUpperCase() + x.slice(1))
5 | .join('');
6 | }
7 |
8 | export function pascalToSnake(s: string): string {
9 | return s.replace(/([A-Z])/g, '_$1').toLowerCase();
10 | }
11 |
--------------------------------------------------------------------------------
/.github/workflows/size.yml:
--------------------------------------------------------------------------------
1 | name: size
2 | on: [pull_request]
3 | jobs:
4 | size:
5 | runs-on: ubuntu-latest
6 | env:
7 | CI_JOB_NUMBER: 1
8 | steps:
9 | - uses: actions/checkout@v1
10 | - uses: andresz1/size-limit-action@v1
11 | with:
12 | github_token: ${{ secrets.GITHUB_TOKEN }}
13 |
--------------------------------------------------------------------------------
/dist/util/paths.d.ts:
--------------------------------------------------------------------------------
1 | /**
2 | * Resolves a file path to an absolute path.
3 | * @param fromFile file from which to calculate
4 | * @param importedPath relative path imported from `fromFile`
5 | * @returns absolute path to the imported file
6 | */
7 | export declare function resolveFileImport(fromFile: string, importedPath: string): string;
8 |
--------------------------------------------------------------------------------
/dist/util/paths.js.map:
--------------------------------------------------------------------------------
1 | {"version":3,"file":"paths.js","sourceRoot":"","sources":["../../src/util/paths.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;AAAA,2CAA6B;AAE7B;;;;;GAKG;AACH,SAAgB,iBAAiB,CAAC,QAAgB,EAAE,YAAoB;IACtE,IAAI,OAAO,GAAG,IAAI,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC,GAAG,CAAC;IACvC,MAAM,YAAY,GAAG,IAAI,CAAC,OAAO,CAAC,OAAO,EAAE,YAAY,CAAC,CAAC;IACzD,OAAO,YAAY,CAAC;AACtB,CAAC;AAJD,8CAIC"}
--------------------------------------------------------------------------------
/dist/bundle.js.LICENSE.txt:
--------------------------------------------------------------------------------
1 | /*!
2 | * Copyright 2016 The ANTLR Project. All rights reserved.
3 | * Licensed under the BSD-3-Clause license. See LICENSE file in the project root for license information.
4 | */
5 |
6 | /*!
7 | * The buffer module from node.js, for the browser.
8 | *
9 | * @author Feross Aboukhadijeh
10 | * @license MIT
11 | */
12 |
--------------------------------------------------------------------------------
/.editorconfig:
--------------------------------------------------------------------------------
1 | root = true
2 |
3 | [*]
4 | charset = utf-8
5 | end_of_line = lf
6 | indent_size = 2
7 | indent_style = space
8 | insert_final_newline = false
9 | max_line_length = 120
10 | tab_width = 4
11 |
12 | [{*.ats,*.cts,*.mts,*.ts}]
13 | tab_width = 2
14 |
15 | [{*.cjs,*.js}]
16 | tab_width = 2
17 |
18 | [{*.har,*.jsb2,*.jsb3,*.json,.babelrc,.eslintrc,.prettierrc,.stylelintrc,bowerrc,jest.config}]
19 | indent_size = 2
20 |
--------------------------------------------------------------------------------
/examples/test-suite/unit/1_errors.cws:
--------------------------------------------------------------------------------
1 | contract TestContractErrors extends BaseContract implements Base_Contract, Hello {
2 |
3 | error SingleErrorUnit
4 | error SingleErrorTuple(String, Uint128)
5 | error SingleErrorStruct(item: Uint128, user: Addr)
6 |
7 | error {
8 | GroupedErrorUnit
9 | GroupedErrorTuple(String, Uint128)
10 | GroupedErrorStruct(item: Uint128, user: Addr)
11 | }
12 | }
--------------------------------------------------------------------------------
/dist/util/strings.js.map:
--------------------------------------------------------------------------------
1 | {"version":3,"file":"strings.js","sourceRoot":"","sources":["../../src/util/strings.ts"],"names":[],"mappings":";;;AAAA,SAAgB,aAAa,CAAC,CAAS;IACrC,OAAO,CAAC;SACL,KAAK,CAAC,GAAG,CAAC;SACV,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,WAAW,EAAE,GAAG,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;SAC3C,IAAI,CAAC,EAAE,CAAC,CAAC;AACd,CAAC;AALD,sCAKC;AAED,SAAgB,aAAa,CAAC,CAAS;IACrC,OAAO,CAAC,CAAC,OAAO,CAAC,UAAU,EAAE,KAAK,CAAC,CAAC,WAAW,EAAE,CAAC;AACpD,CAAC;AAFD,sCAEC"}
--------------------------------------------------------------------------------
/cwsc-x.iml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
--------------------------------------------------------------------------------
/util/print-ast.ts:
--------------------------------------------------------------------------------
1 | function prettyPrint(node: any, depth = 0, field?: string) {
2 | let { $type, $children, ...keys } = node;
3 | let indent = ' '.repeat(depth);
4 | let res = `${indent}${$type}${field !== undefined ? ` (.${field})` : ''}`;
5 | for (let key in keys) {
6 | res += ' ' + key + ': ' + keys[key];
7 | }
8 | console.log(res);
9 | for (let child of $children) {
10 | let { key, value } = child;
11 | prettyPrint(value, depth + 1, key);
12 | }
13 | }
14 |
--------------------------------------------------------------------------------
/bin/dev:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env node
2 |
3 | const oclif = require('@oclif/core')
4 |
5 | const path = require('path')
6 | const project = path.join(__dirname, '..', 'tsconfig.json')
7 |
8 | // In dev mode -> use ts-node and dev plugins
9 | process.env.NODE_ENV = 'development'
10 |
11 | require('ts-node').register({project})
12 |
13 | // In dev mode, always show stack traces
14 | oclif.settings.debug = true;
15 |
16 | // Start the CLI
17 | oclif.run().then(oclif.flush).catch(oclif.Errors.handle)
18 |
--------------------------------------------------------------------------------
/src/util/paths.ts:
--------------------------------------------------------------------------------
1 | import * as path from 'path';
2 |
3 | /**
4 | * Resolves a file path to an absolute path.
5 | * @param fromFile file from which to calculate
6 | * @param importedPath relative path imported from `fromFile`
7 | * @returns absolute path to the imported file
8 | */
9 | export function resolveFileImport(fromFile: string, importedPath: string) {
10 | let baseDir = path.parse(fromFile).dir;
11 | const resolvedPath = path.resolve(baseDir, importedPath);
12 | return resolvedPath;
13 | }
14 |
--------------------------------------------------------------------------------
/dist/util/strings.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 | Object.defineProperty(exports, "__esModule", { value: true });
3 | exports.pascalToSnake = exports.snakeToPascal = void 0;
4 | function snakeToPascal(s) {
5 | return s
6 | .split('_')
7 | .map((x) => x[0].toUpperCase() + x.slice(1))
8 | .join('');
9 | }
10 | exports.snakeToPascal = snakeToPascal;
11 | function pascalToSnake(s) {
12 | return s.replace(/([A-Z])/g, '_$1').toLowerCase();
13 | }
14 | exports.pascalToSnake = pascalToSnake;
15 | //# sourceMappingURL=strings.js.map
--------------------------------------------------------------------------------
/dist/util/symbol-table.d.ts:
--------------------------------------------------------------------------------
1 | type SymbolEnv = {
2 | [key: string]: any;
3 | };
4 | export declare class SymbolTable {
5 | parent?: SymbolTable | undefined;
6 | symbols: SymbolEnv;
7 | constructor(symbols?: SymbolEnv, parent?: SymbolTable | undefined);
8 | getTrail(): SymbolTable[];
9 | getSymbol(name: string): T;
10 | hasSymbol(name: string): boolean;
11 | getOwnSymbol(name: string): T;
12 | setSymbol(name: string, value: any): void;
13 | subscope(x?: T): T;
14 | }
15 | export {};
16 |
--------------------------------------------------------------------------------
/examples/stdlib/stdlib.cws:
--------------------------------------------------------------------------------
1 | impl for T[] {
2 | fn map(self, f: (item: T) -> U) -> U[] {
3 | let result: U[] = [];
4 | for item in self {
5 | result.push(f(item));
6 | }
7 | result
8 | }
9 |
10 | fn map!(self, f: !(item: T) -> U) -> U[] {
11 | let result: U[] = [];
12 | for item in self {
13 | result.push(f!(item));
14 | }
15 | result
16 | }
17 |
18 | fn push(self, item: T) {
19 | self[self.len()] = item;
20 | }
21 |
22 | fn pop() -> T {
23 | let len = self.len();
24 | let item = self[len - 1];
25 | self[len];
26 | item
27 | }
28 | }
29 |
--------------------------------------------------------------------------------
/examples/cw-template/CWTemplate.cws:
--------------------------------------------------------------------------------
1 | contract CWTemplate {
2 |
3 | state {
4 | count: U64
5 | owner: Address
6 | }
7 |
8 | #instantiate(count: U64) {
9 | state.count = count
10 | state.owner = msg.sender
11 | }
12 |
13 | exec #increment() {
14 | $state.count -= 1
15 | }
16 |
17 | exec #reset(count: U64) {
18 | $state.count = count
19 | }
20 |
21 | query #get_count() -> struct { count: U64 } {
22 | return {
23 | count: $state.count
24 | }
25 | }
26 |
27 | query #get_owner() -> struct { owner: Address } {
28 | return {
29 | owner: $state.owner
30 | }
31 | }
32 |
33 | }
34 |
--------------------------------------------------------------------------------
/src/cli/ui/completions.ts:
--------------------------------------------------------------------------------
1 | import omelette from 'omelette';
2 | import fs from 'fs';
3 |
4 | export const completions = omelette(`githubber|gh `);
5 |
6 | // Bind events for every template part.
7 | completions.on('action', ({ reply }) => {
8 | reply(['clone', 'update', 'push']);
9 | });
10 |
11 | completions.on('user', ({ reply }) => {
12 | reply(fs.readdirSync('/Users/'));
13 | });
14 |
15 | completions.on('repo', ({ before, reply }) => {
16 | reply([
17 | `http://github.com/${before}/helloworld`,
18 | `http://github.com/${before}/blabla`,
19 | ]);
20 | });
21 |
22 | // Initialize the omelette.
23 | completions.init();
24 |
--------------------------------------------------------------------------------
/dist/cli/ui/completions.js.map:
--------------------------------------------------------------------------------
1 | {"version":3,"file":"completions.js","sourceRoot":"","sources":["../../../src/cli/ui/completions.ts"],"names":[],"mappings":";;;;;;AAAA,wDAAgC;AAChC,4CAAoB;AAEP,QAAA,WAAW,GAAG,IAAA,kBAAQ,EAAC,qCAAqC,CAAC,CAAC;AAE3E,uCAAuC;AACvC,mBAAW,CAAC,EAAE,CAAC,QAAQ,EAAE,CAAC,EAAE,KAAK,EAAE,EAAE,EAAE;IACrC,KAAK,CAAC,CAAC,OAAO,EAAE,QAAQ,EAAE,MAAM,CAAC,CAAC,CAAC;AACrC,CAAC,CAAC,CAAC;AAEH,mBAAW,CAAC,EAAE,CAAC,MAAM,EAAE,CAAC,EAAE,KAAK,EAAE,EAAE,EAAE;IACnC,KAAK,CAAC,YAAE,CAAC,WAAW,CAAC,SAAS,CAAC,CAAC,CAAC;AACnC,CAAC,CAAC,CAAC;AAEH,mBAAW,CAAC,EAAE,CAAC,MAAM,EAAE,CAAC,EAAE,MAAM,EAAE,KAAK,EAAE,EAAE,EAAE;IAC3C,KAAK,CAAC;QACJ,qBAAqB,MAAM,aAAa;QACxC,qBAAqB,MAAM,SAAS;KACrC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC;AAEH,2BAA2B;AAC3B,mBAAW,CAAC,IAAI,EAAE,CAAC"}
--------------------------------------------------------------------------------
/dist/cli/commands/parse.d.ts:
--------------------------------------------------------------------------------
1 | import { BaseCommand } from '../BaseCommand';
2 | export default class ParseCommand extends BaseCommand {
3 | static description: string;
4 | static examples: string[];
5 | static flags: {
6 | format: import("@oclif/core/lib/interfaces").OptionFlag;
7 | out: import("@oclif/core/lib/interfaces").OptionFlag;
8 | };
9 | static args: {
10 | file: import("@oclif/core/lib/interfaces/parser").Arg;
13 | };
14 | run(): Promise;
15 | }
16 |
--------------------------------------------------------------------------------
/examples/kitchen-sink/kitchen-sink.cws:
--------------------------------------------------------------------------------
1 | interface HasSomething {
2 |
3 | state {
4 | something: struct Something {
5 | the_thing: U123
6 | }
7 | }
8 | }
9 |
10 | interface HasOwner {
11 | state {
12 | owner: String
13 | }
14 |
15 | query #get_owner() -> struct {
16 | owner: String
17 | }
18 | }
19 |
20 |
21 | contract EmptyContract {}
22 |
23 | contract ImplHasSomething implements HasSomething {
24 | query #get_something() {
25 | return {
26 | something: state.something
27 | }
28 | }
29 | }
30 |
31 | contract ImplHasOwner implements HasOwner {
32 | query #get_owner() {
33 | return {
34 | owner: state.owner
35 | }
36 | }
37 | }
38 |
39 | contract ImplHasSomethingAndOwner extends ImplHasSomething {
40 | }
41 |
--------------------------------------------------------------------------------
/examples/test-suite/999_kitchen_sink.cws:
--------------------------------------------------------------------------------
1 | import "standard"
2 | import item, ute from "utica.cws"
3 |
4 | interface IContract {
5 |
6 | }
7 |
8 | interface IHasErrors {
9 |
10 | }
11 |
12 | contract KitchenSink extends ExampleContract
13 | implements IContract, IHasErrors
14 | {
15 |
16 | error SingleUnit
17 | error SingleTuple(String, Uint128)
18 | error SingleStruct(name: String, balance: Uint128)
19 | error SingleStructCurly{
20 | name: String,
21 | balance: Uint128,
22 | }
23 |
24 | event SingleUnit
25 | event SingleTuple(String, String, Uint128)
26 | event SingleStruct(name: String, balance: Uint128)
27 | event SingleStructCurly {
28 | name: String,
29 | balance: Uint128,
30 | }
31 |
32 | instantiate(msg: Uint128, name: String) {
33 | }
34 | }
--------------------------------------------------------------------------------
/.github/workflows/main.yml:
--------------------------------------------------------------------------------
1 | name: CI
2 | on: [push]
3 | jobs:
4 | build:
5 | name: Build, lint, and test on Node ${{ matrix.node }} and ${{ matrix.os }}
6 |
7 | runs-on: ${{ matrix.os }}
8 | strategy:
9 | matrix:
10 | node: ['10.x', '12.x', '14.x']
11 | os: [ubuntu-latest, windows-latest, macOS-latest]
12 |
13 | steps:
14 | - name: Checkout repo
15 | uses: actions/checkout@v2
16 |
17 | - name: Use Node ${{ matrix.node }}
18 | uses: actions/setup-node@v1
19 | with:
20 | node-version: ${{ matrix.node }}
21 |
22 | - name: Install deps and build (with cache)
23 | uses: bahmutov/npm-install@v1
24 |
25 | - name: Lint
26 | run: yarn lint
27 |
28 | - name: Test
29 | run: yarn test --ci --coverage --maxWorkers=2
30 |
31 | - name: Build
32 | run: yarn build
33 |
--------------------------------------------------------------------------------
/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "include": [
3 | "src",
4 | "types"
5 | ],
6 | "exclude": [
7 | "/node_modules/",
8 | "./src/**/*.test.ts"
9 | ],
10 | "compilerOptions": {
11 | "allowSyntheticDefaultImports": true,
12 | "alwaysStrict": true,
13 | "baseUrl": "./",
14 | "declaration": true,
15 | "esModuleInterop": true,
16 | "lib": [
17 | "es2016",
18 | "es2017",
19 | "dom"
20 | ],
21 | "module": "commonjs",
22 | "moduleResolution": "node",
23 | "noFallthroughCasesInSwitch": true,
24 | "noImplicitAny": true,
25 | "noImplicitReturns": true,
26 | "noImplicitThis": true,
27 | "noUnusedLocals": false,
28 | "noUnusedParameters": false,
29 | "downlevelIteration": true,
30 | "outDir": "dist",
31 | "rootDir": "src",
32 | "sourceMap": true,
33 | "strict": true,
34 | "strictFunctionTypes": true,
35 | "strictNullChecks": true,
36 | "strictPropertyInitialization": true,
37 | "target": "es2017"
38 | }
39 | }
40 |
--------------------------------------------------------------------------------
/dist/cli/ui/completions.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 | var __importDefault = (this && this.__importDefault) || function (mod) {
3 | return (mod && mod.__esModule) ? mod : { "default": mod };
4 | };
5 | Object.defineProperty(exports, "__esModule", { value: true });
6 | exports.completions = void 0;
7 | const omelette_1 = __importDefault(require("omelette"));
8 | const fs_1 = __importDefault(require("fs"));
9 | exports.completions = (0, omelette_1.default)(`githubber|gh `);
10 | // Bind events for every template part.
11 | exports.completions.on('action', ({ reply }) => {
12 | reply(['clone', 'update', 'push']);
13 | });
14 | exports.completions.on('user', ({ reply }) => {
15 | reply(fs_1.default.readdirSync('/Users/'));
16 | });
17 | exports.completions.on('repo', ({ before, reply }) => {
18 | reply([
19 | `http://github.com/${before}/helloworld`,
20 | `http://github.com/${before}/blabla`,
21 | ]);
22 | });
23 | // Initialize the omelette.
24 | exports.completions.init();
25 | //# sourceMappingURL=completions.js.map
--------------------------------------------------------------------------------
/LICENSE.md:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2023 Web, Inc.
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 |
--------------------------------------------------------------------------------
/examples/test-contract/test-contract.cws:
--------------------------------------------------------------------------------
1 | contract MyTestContract {
2 |
3 | event Instantiate(owner: Addr, count: u32)
4 | event Call(method: String)
5 |
6 | error Unauthorized{}
7 |
8 | state {
9 | count: u32
10 | owner: Addr
11 | }
12 |
13 | instantiate(count: u32) {
14 | state.count = count
15 | state.owner = msg.sender
16 |
17 | emit Instantiate(msg.sender, count)
18 | }
19 |
20 | exec increment() {
21 | if count == None {
22 | state.count += 1
23 | } else {
24 | state.count += count
25 | }
26 |
27 | emit Call("increment")
28 | }
29 |
30 | exec reset(count: u32) {
31 | if msg.sender != state.owner {
32 | fail Unauthorized{}
33 | }
34 |
35 | state.count = count
36 | emit Call("reset")
37 | }
38 |
39 | query get_count() -> struct _ { count: u32 } {
40 | return _ {
41 | count: state.count
42 | }
43 | }
44 |
45 | query get_owner() -> struct _ { owner: Addr } {
46 | return _ {
47 | owner: state.owner
48 | }
49 | }
50 | }
--------------------------------------------------------------------------------
/dist/cli/commands/parse.js.map:
--------------------------------------------------------------------------------
1 | {"version":3,"file":"parse.js","sourceRoot":"","sources":["../../../src/cli/commands/parse.ts"],"names":[],"mappings":";;;;;AAAA,sCAAmD;AACnD,gDAA4D;AAC5D,yCAAyC;AACzC,4CAAoB;AAMpB,MAAqB,YAAa,SAAQ,yBAAgC;IA+BjE,KAAK,CAAC,GAAG;QACd,MAAM,EAAE,IAAI,EAAE,KAAK,EAAE,GAAG,MAAM,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,CAAC;QACvD,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE;YACd,IAAI,CAAC,KAAK,CAAC,4BAA4B,CAAC,CAAC;SAC1C;QAED,IAAI,CAAC,KAAK,CAAC,WAAW,IAAI,CAAC,IAAI,SAAS,KAAK,CAAC,MAAM,KAAK,CAAC,CAAC;QAC3D,IAAI,WAAW,GAAG,YAAE,CAAC,YAAY,CAAC,IAAI,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC;QACrD,IAAI,GAAG,GAAG,IAAI,kBAAS,CAAC,WAAW,EAAE,IAAI,CAAC,IAAI,CAAC,CAAC,KAAK,EAAE,CAAC;QACxD,IAAI,KAAK,CAAC,GAAG,EAAE;YACb,YAAE,CAAC,aAAa,CAAC,KAAK,CAAC,GAAG,EAAE,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC;SAC3D;aAAM;YACL,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC,MAAM,EAAE,CAAC,CAAC;SAC3B;IACH,CAAC;;AA7CH,+BA8CC;AA7CQ,wBAAW,GAAG,wCAAwC,CAAC;AAEvD,qBAAQ,GAAG;IAChB,0CAA0C;IAC1C,wDAAwD;CACzD,CAAC;AAEK,kBAAK,GAAG;IACb,MAAM,EAAE,YAAK,CAAC,MAAM,CAAC;QACnB,WAAW,EAAE,yCAAyC;QACtD,QAAQ,EAAE,IAAI;QACd,OAAO,EAAE,CAAC,MAAM,EAAE,MAAM,CAAC;QACzB,OAAO,EAAE,MAAM;KAChB,CAAC;IACF,GAAG,EAAE,YAAK,CAAC,MAAM,CAAC;QAChB,IAAI,EAAE,GAAG;QACT,WAAW,EAAE,wCAAwC;QACrD,QAAQ,EAAE,KAAK;KAChB,CAAC;CACH,CAAC;AAEK,iBAAI,GAAG;IACZ,IAAI,EAAE,WAAI,CAAC,IAAI,CAAC;QACd,WAAW,EAAE,yBAAyB;QACtC,QAAQ,EAAE,IAAI;QACd,WAAW,EAAE,IAAI;QACjB,MAAM,EAAE,IAAI;KACb,CAAC;CACH,CAAC"}
--------------------------------------------------------------------------------
/dist/util/result.d.ts:
--------------------------------------------------------------------------------
1 | import { Diagnostic } from 'vscode-languageserver';
2 | import { Result, Ok, Err } from 'ts-results';
3 | export type DgnsOk = DgnsResult>;
4 | export type DgnsErr = DgnsResult>;
5 | export declare class CWSValidationError extends Error {
6 | diagnostics: Diagnostic[];
7 | constructor(diagnostics: Diagnostic[]);
8 | }
9 | export declare class DgnsResult = Result> {
10 | res: R;
11 | diagnostics: Diagnostic[];
12 | constructor(res: R, diagnostics: Diagnostic[]);
13 | static Ok(res: T, diagnostics: Diagnostic[]): DgnsOk;
14 | static Err(err: E, diagnostics: Diagnostic[]): DgnsErr;
15 | isOk(): this is DgnsOk;
16 | isErr(): this is DgnsErr;
17 | map(f: (t: T, d: Diagnostic[]) => U): DgnsResult;
18 | mapErr(f: (e: E, d: Diagnostic[]) => U): DgnsResult;
19 | flatMap: (f: (r: T, d: Diagnostic[]) => DgnsResult>) => DgnsResult>;
20 | andThen(f: (r: T, d: Diagnostic[]) => DgnsResult): DgnsResult;
21 | unwrap(): T;
22 | static all(results: DgnsResult[]): DgnsResult;
23 | static allOk(results: DgnsOk[]): DgnsOk;
24 | static allErr(results: DgnsErr[]): DgnsErr;
25 | catchErr(errC: new (...args: any[]) => F, f: (e: F, d: Diagnostic[]) => DgnsResult): DgnsResult;
26 | }
27 |
--------------------------------------------------------------------------------
/.vscode/launch.json:
--------------------------------------------------------------------------------
1 | {
2 | // Use IntelliSense to learn about possible attributes.
3 | // Hover to view descriptions of existing attributes.
4 | // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
5 | "version": "0.2.0",
6 | "configurations": [
7 | {
8 | "name": "Debug CWScript Grammar",
9 | "type": "antlr-debug",
10 | "request": "launch",
11 | "input": "examples/cws-cw20/src/cw20-base.cws",
12 | "grammar": "grammar/CWScriptParser.g4",
13 | "startRule": "sourceFile",
14 | "printParseTree": true,
15 | "visualParseTree": true
16 | },
17 | // {
18 | // "name": "Debug CWSpec Grammar",
19 | // "type": "antlr-debug",
20 | // "request": "launch",
21 | // "input": "examples/cws-cw20/src/cw20-base.cwspec",
22 | // "grammar": "grammar/CWSpecParser.g4",
23 | // "startRule": "cwspec",
24 | // "printParseTree": true,
25 | // "visualParseTree": true
26 | // }
27 | {
28 | "name": "Debug CWScript Compiler",
29 | "type": "node",
30 | "request": "launch",
31 | "runtimeArgs": ["--nolazy", "-r", "ts-node/register"],
32 | "args": ["src/cli.ts", "examples/cws-cw20/src/cw20-base.cws"],
33 | "cwd": "${workspaceFolder}",
34 | "internalConsoleOptions": "openOnSessionStart",
35 | "skipFiles": ["/**", "node_modules/**"],
36 | "env": {
37 | "TS_NODE_PROJECT": "${workspaceFolder}/tsconfig.json"
38 | }
39 | }
40 | ]
41 | }
42 |
--------------------------------------------------------------------------------
/dist/cli/BaseCommand.d.ts:
--------------------------------------------------------------------------------
1 | import { Command, Interfaces } from '@oclif/core';
2 | export type FlagsT = Interfaces.InferredFlags;
3 | export type ArgsT = Interfaces.InferredArgs;
4 | export declare class ConfigKV {
5 | key: string;
6 | value: string;
7 | constructor(key: string, value: string);
8 | }
9 | export declare abstract class BaseCommand extends Command {
10 | loadConfig(): Promise;
11 | protected flags: FlagsT;
12 | protected args: ArgsT;
13 | init(): Promise;
14 | static baseFlags: {
15 | verbose: Interfaces.BooleanFlag;
16 | silent: Interfaces.BooleanFlag;
17 | 'show-hints': Interfaces.BooleanFlag;
18 | 'show-warnings': Interfaces.BooleanFlag;
19 | logs: Interfaces.OptionFlag;
20 | 'log-file': Interfaces.OptionFlag;
21 | 'project-dir': Interfaces.OptionFlag;
22 | cwsconfig: Interfaces.OptionFlag;
23 | };
24 | protected catch(err: Error & {
25 | exitCode?: number;
26 | }): Promise;
27 | protected finally(_: Error | undefined): Promise;
28 | abstract run(): Promise;
29 | }
30 |
--------------------------------------------------------------------------------
/dist/index.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 | var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3 | if (k2 === undefined) k2 = k;
4 | var desc = Object.getOwnPropertyDescriptor(m, k);
5 | if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6 | desc = { enumerable: true, get: function() { return m[k]; } };
7 | }
8 | Object.defineProperty(o, k2, desc);
9 | }) : (function(o, m, k, k2) {
10 | if (k2 === undefined) k2 = k;
11 | o[k2] = m[k];
12 | }));
13 | var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14 | Object.defineProperty(o, "default", { enumerable: true, value: v });
15 | }) : function(o, v) {
16 | o["default"] = v;
17 | });
18 | var __importStar = (this && this.__importStar) || function (mod) {
19 | if (mod && mod.__esModule) return mod;
20 | var result = {};
21 | if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
22 | __setModuleDefault(result, mod);
23 | return result;
24 | };
25 | Object.defineProperty(exports, "__esModule", { value: true });
26 | exports.AST = exports.CWSInterpreter = exports.CWSParser = void 0;
27 | var parser_1 = require("./parser");
28 | Object.defineProperty(exports, "CWSParser", { enumerable: true, get: function () { return parser_1.CWSParser; } });
29 | var interpreter_1 = require("./interpreter");
30 | Object.defineProperty(exports, "CWSInterpreter", { enumerable: true, get: function () { return interpreter_1.CWSInterpreter; } });
31 | exports.AST = __importStar(require("./ast"));
32 | //# sourceMappingURL=index.js.map
--------------------------------------------------------------------------------
/dist/util/symbol-table.js.map:
--------------------------------------------------------------------------------
1 | {"version":3,"file":"symbol-table.js","sourceRoot":"","sources":["../../src/util/symbol-table.ts"],"names":[],"mappings":";;;AAIA,MAAa,WAAW;IAGtB,YAAY,OAAmB,EAAS,MAAoB;QAApB,WAAM,GAAN,MAAM,CAAc;QAC1D,IAAI,CAAC,OAAO,GAAG,OAAO,aAAP,OAAO,cAAP,OAAO,GAAI,EAAE,CAAC;IAC/B,CAAC;IAED,QAAQ;QACN,IAAI,GAAG,GAAkB,CAAC,IAAI,CAAC,CAAC;QAChC,IAAI,GAAG,GAAG,IAAI,CAAC,MAAM,CAAC;QACtB,OAAO,GAAG,EAAE;YACV,GAAG,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;YACd,GAAG,GAAG,GAAG,CAAC,MAAM,CAAC;SAClB;QACD,OAAO,GAAG,CAAC,OAAO,EAAE,CAAC;IACvB,CAAC;IAED,SAAS,CAAU,IAAY;QAC7B,IAAI,IAAI,IAAI,IAAI,CAAC,OAAO,EAAE;YACxB,OAAO,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;SAC3B;QAED,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,CAAC,OAAO,EAAE;YAC/B,OAAO,IAAI,CAAC,OAAO,CAAC,IAAI,GAAG,IAAI,CAAC,CAAC;SAClC;QAED,IAAI,IAAI,CAAC,MAAM,EAAE;YACf,OAAO,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC;SACpC;QAED,MAAM,IAAI,KAAK,CAAC,UAAU,IAAI,YAAY,CAAC,CAAC;IAC9C,CAAC;IAED,SAAS,CAAC,IAAY;QACpB,IAAI,GAAG,GAAG,IAAI,IAAI,IAAI,CAAC,OAAO,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,CAAC,OAAO,CAAC;QAC9D,IAAI,GAAG,EAAE;YACP,OAAO,IAAI,CAAC;SACb;aAAM;YACL,OAAO,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC;SAC1D;IACH,CAAC;IAED,YAAY,CAAU,IAAY;QAChC,IAAI,IAAI,IAAI,IAAI,CAAC,OAAO,EAAE;YACxB,OAAO,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;SAC3B;QAED,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,CAAC,OAAO,EAAE;YAC/B,OAAO,IAAI,CAAC,OAAO,CAAC,IAAI,GAAG,IAAI,CAAC,CAAC;SAClC;QAED,MAAM,IAAI,KAAK,CAAC,UAAU,IAAI,YAAY,CAAC,CAAC;IAC9C,CAAC;IAED,SAAS,CAAC,IAAY,EAAE,KAAU;QAChC,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,GAAG,KAAK,CAAC;IAC7B,CAAC;IAED,QAAQ,CAAsC,CAAK;QACjD,IAAI,CAAC,KAAK,SAAS,EAAE;YACnB,IAAI,GAAG,GAAG,IAAI,WAAW,EAAE,CAAC;YAC5B,GAAG,CAAC,MAAM,GAAG,IAAI,CAAC;YAClB,OAAO,GAAQ,CAAC;SACjB;aAAM;YACL,CAAC,CAAC,MAAM,GAAG,IAAI,CAAC;YAChB,OAAO,CAAC,CAAC;SACV;IACH,CAAC;CACF;AApED,kCAoEC"}
--------------------------------------------------------------------------------
/dist/util/paths.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 | var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3 | if (k2 === undefined) k2 = k;
4 | var desc = Object.getOwnPropertyDescriptor(m, k);
5 | if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6 | desc = { enumerable: true, get: function() { return m[k]; } };
7 | }
8 | Object.defineProperty(o, k2, desc);
9 | }) : (function(o, m, k, k2) {
10 | if (k2 === undefined) k2 = k;
11 | o[k2] = m[k];
12 | }));
13 | var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14 | Object.defineProperty(o, "default", { enumerable: true, value: v });
15 | }) : function(o, v) {
16 | o["default"] = v;
17 | });
18 | var __importStar = (this && this.__importStar) || function (mod) {
19 | if (mod && mod.__esModule) return mod;
20 | var result = {};
21 | if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
22 | __setModuleDefault(result, mod);
23 | return result;
24 | };
25 | Object.defineProperty(exports, "__esModule", { value: true });
26 | exports.resolveFileImport = void 0;
27 | const path = __importStar(require("path"));
28 | /**
29 | * Resolves a file path to an absolute path.
30 | * @param fromFile file from which to calculate
31 | * @param importedPath relative path imported from `fromFile`
32 | * @returns absolute path to the imported file
33 | */
34 | function resolveFileImport(fromFile, importedPath) {
35 | let baseDir = path.parse(fromFile).dir;
36 | const resolvedPath = path.resolve(baseDir, importedPath);
37 | return resolvedPath;
38 | }
39 | exports.resolveFileImport = resolveFileImport;
40 | //# sourceMappingURL=paths.js.map
--------------------------------------------------------------------------------
/src/util/symbol-table.ts:
--------------------------------------------------------------------------------
1 | type SymbolEnv = {
2 | [key: string]: any;
3 | };
4 |
5 | export class SymbolTable {
6 | public symbols: SymbolEnv;
7 |
8 | constructor(symbols?: SymbolEnv, public parent?: SymbolTable) {
9 | this.symbols = symbols ?? {};
10 | }
11 |
12 | getTrail(): SymbolTable[] {
13 | let res: SymbolTable[] = [this];
14 | let cur = this.parent;
15 | while (cur) {
16 | res.push(cur);
17 | cur = cur.parent;
18 | }
19 | return res.reverse();
20 | }
21 |
22 | getSymbol(name: string): T {
23 | if (name in this.symbols) {
24 | return this.symbols[name];
25 | }
26 |
27 | if (name + '#!' in this.symbols) {
28 | return this.symbols[name + '#!'];
29 | }
30 |
31 | if (this.parent) {
32 | return this.parent.getSymbol(name);
33 | }
34 |
35 | throw new Error(`symbol ${name} not found`);
36 | }
37 |
38 | hasSymbol(name: string): boolean {
39 | let res = name in this.symbols || name + '#!' in this.symbols;
40 | if (res) {
41 | return true;
42 | } else {
43 | return this.parent ? this.parent.hasSymbol(name) : false;
44 | }
45 | }
46 |
47 | getOwnSymbol(name: string): T {
48 | if (name in this.symbols) {
49 | return this.symbols[name];
50 | }
51 |
52 | if (name + '#!' in this.symbols) {
53 | return this.symbols[name + '#!'];
54 | }
55 |
56 | throw new Error(`symbol ${name} not found`);
57 | }
58 |
59 | setSymbol(name: string, value: any) {
60 | this.symbols[name] = value;
61 | }
62 |
63 | subscope(x?: T): T {
64 | if (x === undefined) {
65 | let res = new SymbolTable();
66 | res.parent = this;
67 | return res as T;
68 | } else {
69 | x.parent = this;
70 | return x;
71 | }
72 | }
73 | }
74 |
--------------------------------------------------------------------------------
/src/cli/commands/parse.ts:
--------------------------------------------------------------------------------
1 | import { Command, Args, Flags } from '@oclif/core';
2 | import { BaseCommand, FlagsT, ArgsT } from '../BaseCommand';
3 | import { CWSParser } from '../../parser';
4 | import fs from 'fs';
5 | import path from 'path';
6 | import { DiagnosticSeverity } from 'vscode-languageserver';
7 | import { TextView } from '../../util/position';
8 | import { errorReportWithCodeSnippet } from '../../util/diagnostics';
9 |
10 | export default class ParseCommand extends BaseCommand {
11 | static description = 'Parse a CWScript source file into AST.';
12 |
13 | static examples = [
14 | `<%= config.bin %> <%= command.id %> FILE`,
15 | `<%= config.bin %> <%= command.id %> FILE --format sexp`,
16 | ];
17 |
18 | static flags = {
19 | format: Flags.string({
20 | description: 'Desired format of the parsed AST output',
21 | required: true,
22 | options: ['json', 'sexp'],
23 | default: 'json',
24 | }),
25 | out: Flags.string({
26 | char: 'o',
27 | description: 'Output file to write the parsed AST to',
28 | required: false,
29 | }),
30 | };
31 |
32 | static args = {
33 | file: Args.file({
34 | description: 'File to parse into AST.',
35 | required: true,
36 | ignoreStdin: true,
37 | exists: true,
38 | }),
39 | };
40 |
41 | public async run() {
42 | const { args, flags } = await this.parse(ParseCommand);
43 | if (!args.file) {
44 | this.error('No file provided to parse.');
45 | }
46 |
47 | this.debug(`Parsing ${args.file} into ${flags.format}...`);
48 | let sourceInput = fs.readFileSync(args.file, 'utf8');
49 | let ast = new CWSParser(sourceInput, args.file).parse();
50 | if (flags.out) {
51 | fs.writeFileSync(flags.out, JSON.stringify(ast.toJSON()));
52 | } else {
53 | console.log(ast.toJSON());
54 | }
55 | }
56 | }
57 |
--------------------------------------------------------------------------------
/dist/parser/index.d.ts:
--------------------------------------------------------------------------------
1 | import { ANTLRErrorListener } from 'antlr4ts';
2 | import { SourceFileContext } from '../grammar/CWScriptParser';
3 | import * as AST from '../ast';
4 | import { Diagnostic } from 'vscode-languageserver';
5 | import * as P from '../grammar/CWScriptParser';
6 | import { CWScriptParserListener } from '../grammar/CWScriptParserListener';
7 | import { RecognitionException } from 'antlr4ts/RecognitionException';
8 | export declare abstract class CWSDiagnosticsCollector {
9 | diagnostics: Diagnostic[];
10 | get errors(): Diagnostic[];
11 | get warnings(): Diagnostic[];
12 | get infos(): Diagnostic[];
13 | get hints(): Diagnostic[];
14 | }
15 | export declare class CWSSyntaxErrorListener implements ANTLRErrorListener {
16 | parser: CWSParser;
17 | constructor(parser: CWSParser);
18 | syntaxError(recognizer: any, offendingSymbol: any, line: number, charPositionInLine: number, msg: string, e: RecognitionException | undefined): void;
19 | }
20 | export declare class CheckSymbolsDeclaredBeforeUse implements CWScriptParserListener {
21 | parser: CWSParser;
22 | scopes: any;
23 | get scope(): any;
24 | constructor(parser: CWSParser);
25 | enterIdentExpr(ctx: P.IdentExprContext): void;
26 | enterIdentBinding_(ctx: P.IdentBinding_Context): void;
27 | enterImportItemsStmt(ctx: P.ImportItemsStmtContext): void;
28 | enterParam(ctx: P.ParamContext): void;
29 | enterInstantiateDefn(ctx: P.InstantiateDefnContext): void;
30 | enterFnDefn(ctx: P.FnDefnContext): void;
31 | enterStructDefn(ctx: P.StructDefnContext): void;
32 | enterEnumDefn(ctx: P.EnumDefnContext): void;
33 | }
34 | export declare class CWSParser extends CWSDiagnosticsCollector {
35 | sourceInput: string;
36 | constructor(sourceInput: string, sourceFile?: string | null);
37 | /**
38 | * This is the public-facing interface for parsing a source file.
39 | */
40 | parse(): AST.SourceFile;
41 | protected antlrParse(): SourceFileContext;
42 | }
43 |
--------------------------------------------------------------------------------
/dist/util/symbol-table.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 | Object.defineProperty(exports, "__esModule", { value: true });
3 | exports.SymbolTable = void 0;
4 | class SymbolTable {
5 | constructor(symbols, parent) {
6 | this.parent = parent;
7 | this.symbols = symbols !== null && symbols !== void 0 ? symbols : {};
8 | }
9 | getTrail() {
10 | let res = [this];
11 | let cur = this.parent;
12 | while (cur) {
13 | res.push(cur);
14 | cur = cur.parent;
15 | }
16 | return res.reverse();
17 | }
18 | getSymbol(name) {
19 | if (name in this.symbols) {
20 | return this.symbols[name];
21 | }
22 | if (name + '#!' in this.symbols) {
23 | return this.symbols[name + '#!'];
24 | }
25 | if (this.parent) {
26 | return this.parent.getSymbol(name);
27 | }
28 | throw new Error(`symbol ${name} not found`);
29 | }
30 | hasSymbol(name) {
31 | let res = name in this.symbols || name + '#!' in this.symbols;
32 | if (res) {
33 | return true;
34 | }
35 | else {
36 | return this.parent ? this.parent.hasSymbol(name) : false;
37 | }
38 | }
39 | getOwnSymbol(name) {
40 | if (name in this.symbols) {
41 | return this.symbols[name];
42 | }
43 | if (name + '#!' in this.symbols) {
44 | return this.symbols[name + '#!'];
45 | }
46 | throw new Error(`symbol ${name} not found`);
47 | }
48 | setSymbol(name, value) {
49 | this.symbols[name] = value;
50 | }
51 | subscope(x) {
52 | if (x === undefined) {
53 | let res = new SymbolTable();
54 | res.parent = this;
55 | return res;
56 | }
57 | else {
58 | x.parent = this;
59 | return x;
60 | }
61 | }
62 | }
63 | exports.SymbolTable = SymbolTable;
64 | //# sourceMappingURL=symbol-table.js.map
--------------------------------------------------------------------------------
/dist/cli/commands/parse.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 | var __importDefault = (this && this.__importDefault) || function (mod) {
3 | return (mod && mod.__esModule) ? mod : { "default": mod };
4 | };
5 | Object.defineProperty(exports, "__esModule", { value: true });
6 | const core_1 = require("@oclif/core");
7 | const BaseCommand_1 = require("../BaseCommand");
8 | const parser_1 = require("../../parser");
9 | const fs_1 = __importDefault(require("fs"));
10 | class ParseCommand extends BaseCommand_1.BaseCommand {
11 | async run() {
12 | const { args, flags } = await this.parse(ParseCommand);
13 | if (!args.file) {
14 | this.error('No file provided to parse.');
15 | }
16 | this.debug(`Parsing ${args.file} into ${flags.format}...`);
17 | let sourceInput = fs_1.default.readFileSync(args.file, 'utf8');
18 | let ast = new parser_1.CWSParser(sourceInput, args.file).parse();
19 | if (flags.out) {
20 | fs_1.default.writeFileSync(flags.out, JSON.stringify(ast.toJSON()));
21 | }
22 | else {
23 | console.log(ast.toJSON());
24 | }
25 | }
26 | }
27 | exports.default = ParseCommand;
28 | ParseCommand.description = 'Parse a CWScript source file into AST.';
29 | ParseCommand.examples = [
30 | `<%= config.bin %> <%= command.id %> FILE`,
31 | `<%= config.bin %> <%= command.id %> FILE --format sexp`,
32 | ];
33 | ParseCommand.flags = {
34 | format: core_1.Flags.string({
35 | description: 'Desired format of the parsed AST output',
36 | required: true,
37 | options: ['json', 'sexp'],
38 | default: 'json',
39 | }),
40 | out: core_1.Flags.string({
41 | char: 'o',
42 | description: 'Output file to write the parsed AST to',
43 | required: false,
44 | }),
45 | };
46 | ParseCommand.args = {
47 | file: core_1.Args.file({
48 | description: 'File to parse into AST.',
49 | required: true,
50 | ignoreStdin: true,
51 | exists: true,
52 | }),
53 | };
54 | //# sourceMappingURL=parse.js.map
--------------------------------------------------------------------------------
/src/util/diagnostics.ts:
--------------------------------------------------------------------------------
1 | import { TextView } from './position';
2 | import { Diagnostic } from 'vscode-languageserver';
3 |
4 | import chalk from 'chalk';
5 |
6 | export function errorReportWithCodeSnippet(
7 | filename: string,
8 | sourceText: TextView,
9 | diagnostic: Diagnostic
10 | ) {
11 | let res = '';
12 | let { range, message } = diagnostic;
13 | let filenameWithRange = `${filename}:${range.start.line + 1}:${
14 | range.start.character + 1
15 | }-${range.end.line + 1}:${range.end.character + 1}`;
16 | res += `[ERROR] ${filenameWithRange}\n`;
17 | res += `${message}\n\n...\n`;
18 |
19 | let lineNoWidth = 5;
20 | let gutterWidth = lineNoWidth + 2;
21 | let makeLine = (line: number, text: string) => {
22 | return chalk.dim(
23 | `${line.toString().padStart(lineNoWidth, ' ')}| ${text}\n`
24 | );
25 | };
26 | let makeErrorLine = (line: number, text: string) => {
27 | return `${chalk.redBright(
28 | chalk.bold(line.toString().padStart(lineNoWidth, ' ')) + '|'
29 | )} ${text}\n`;
30 | };
31 |
32 | sourceText.surroundingLinesOfRange(range, 5).forEach((x) => {
33 | // if this is the starting line, make a pointer
34 | // if range.start.line <= x.line <= range.end.line, highlight the line
35 | if (x.line >= range.start.line && x.line <= range.end.line) {
36 | // only highlight the part of the line that is in the range
37 | let start = x.line === range.start.line ? range.start.character : 0;
38 | let end = x.line === range.end.line ? range.end.character : x.text.length;
39 | res += makeErrorLine(
40 | x.line,
41 | chalk.dim(x.text.slice(0, start)) +
42 | chalk.bold(chalk.redBright(x.text.slice(start, end))) +
43 | chalk.dim(x.text.slice(end))
44 | );
45 | if (x.line === range.end.line) {
46 | res += chalk.bold(
47 | chalk.yellow(
48 | ' '.repeat(gutterWidth + range.end.character) +
49 | '^ ' +
50 | message +
51 | '\n'
52 | )
53 | );
54 | }
55 | } else {
56 | res += makeLine(x.line, x.text);
57 | }
58 | });
59 | res += `...\n\n`;
60 | return res;
61 | }
62 |
--------------------------------------------------------------------------------
/dist/util/diagnostics.js.map:
--------------------------------------------------------------------------------
1 | {"version":3,"file":"diagnostics.js","sourceRoot":"","sources":["../../src/util/diagnostics.ts"],"names":[],"mappings":"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"}
--------------------------------------------------------------------------------
/webpack.config.js:
--------------------------------------------------------------------------------
1 | const webpack = require('webpack');
2 | const TsconfigPathsPlugin = require('tsconfig-paths-webpack-plugin');
3 | const TerserPlugin = require('terser-webpack-plugin');
4 | const { resolve } = require('path');
5 |
6 | // const BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin;
7 |
8 | const commonConfig = {
9 | mode: 'production',
10 | entry: ['./src/index.ts'],
11 | devtool: 'source-map',
12 | output: {
13 | globalObject: 'this',
14 | },
15 | module: {
16 | rules: [
17 | {
18 | test: /\.tsx?/,
19 | use: { loader: 'ts-loader' },
20 | exclude: /node_modules/,
21 | },
22 | ],
23 | },
24 | resolve: {
25 | extensions: ['.tsx', '.ts', '.js'],
26 | plugins: [new TsconfigPathsPlugin()],
27 | },
28 | plugins: [
29 | new webpack.IgnorePlugin({
30 | resourceRegExp:
31 | /wordlists\/(french|spanish|italian|korean|chinese_simplified|chinese_traditional|japanese)\.json$/,
32 | }),
33 | ],
34 | };
35 |
36 | const webConfig = {
37 | ...commonConfig,
38 | target: 'web',
39 | output: {
40 | filename: 'bundle.js',
41 | libraryTarget: 'umd',
42 | library: 'cwsc',
43 | },
44 | resolve: {
45 | ...commonConfig.resolve,
46 | fallback: {
47 | stream: require.resolve('stream-browserify'),
48 | path: require.resolve('path-browserify'),
49 | buffer: require.resolve('buffer'),
50 | assert: require.resolve('assert'),
51 | 'process/browser': require.resolve('process'),
52 | },
53 | },
54 | plugins: [
55 | ...commonConfig.plugins,
56 | new webpack.ProvidePlugin({
57 | Buffer: ['buffer', 'Buffer'],
58 | }),
59 | new webpack.ProvidePlugin({
60 | process: 'process/browser',
61 | }),
62 | // new BundleAnalyzerPlugin(),
63 | ],
64 | optimization: {
65 | minimize: true,
66 | minimizer: [
67 | new TerserPlugin({
68 | terserOptions: {
69 | keep_classnames: true,
70 | },
71 | }),
72 | ],
73 | },
74 | };
75 |
76 | const nodeConfig = {
77 | ...commonConfig,
78 | target: 'node',
79 | output: {
80 | libraryTarget: 'commonjs',
81 | filename: 'bundle.node.js',
82 | },
83 | };
84 |
85 | module.exports = [webConfig, nodeConfig];
86 |
--------------------------------------------------------------------------------
/dist/cli/BaseCommand.js.map:
--------------------------------------------------------------------------------
1 | {"version":3,"file":"BaseCommand.js","sourceRoot":"","sources":["../../src/cli/BaseCommand.ts"],"names":[],"mappings":"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"}
--------------------------------------------------------------------------------
/dist/util/diagnostics.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 | var __importDefault = (this && this.__importDefault) || function (mod) {
3 | return (mod && mod.__esModule) ? mod : { "default": mod };
4 | };
5 | Object.defineProperty(exports, "__esModule", { value: true });
6 | exports.errorReportWithCodeSnippet = void 0;
7 | const chalk_1 = __importDefault(require("chalk"));
8 | function errorReportWithCodeSnippet(filename, sourceText, diagnostic) {
9 | let res = '';
10 | let { range, message } = diagnostic;
11 | let filenameWithRange = `${filename}:${range.start.line + 1}:${range.start.character + 1}-${range.end.line + 1}:${range.end.character + 1}`;
12 | res += `[ERROR] ${filenameWithRange}\n`;
13 | res += `${message}\n\n...\n`;
14 | let lineNoWidth = 5;
15 | let gutterWidth = lineNoWidth + 2;
16 | let makeLine = (line, text) => {
17 | return chalk_1.default.dim(`${line.toString().padStart(lineNoWidth, ' ')}| ${text}\n`);
18 | };
19 | let makeErrorLine = (line, text) => {
20 | return `${chalk_1.default.redBright(chalk_1.default.bold(line.toString().padStart(lineNoWidth, ' ')) + '|')} ${text}\n`;
21 | };
22 | sourceText.surroundingLinesOfRange(range, 5).forEach((x) => {
23 | // if this is the starting line, make a pointer
24 | // if range.start.line <= x.line <= range.end.line, highlight the line
25 | if (x.line >= range.start.line && x.line <= range.end.line) {
26 | // only highlight the part of the line that is in the range
27 | let start = x.line === range.start.line ? range.start.character : 0;
28 | let end = x.line === range.end.line ? range.end.character : x.text.length;
29 | res += makeErrorLine(x.line, chalk_1.default.dim(x.text.slice(0, start)) +
30 | chalk_1.default.bold(chalk_1.default.redBright(x.text.slice(start, end))) +
31 | chalk_1.default.dim(x.text.slice(end)));
32 | if (x.line === range.end.line) {
33 | res += chalk_1.default.bold(chalk_1.default.yellow(' '.repeat(gutterWidth + range.end.character) +
34 | '^ ' +
35 | message +
36 | '\n'));
37 | }
38 | }
39 | else {
40 | res += makeLine(x.line, x.text);
41 | }
42 | });
43 | res += `...\n\n`;
44 | return res;
45 | }
46 | exports.errorReportWithCodeSnippet = errorReportWithCodeSnippet;
47 | //# sourceMappingURL=diagnostics.js.map
--------------------------------------------------------------------------------
/grammar/CWScriptLexer.g4:
--------------------------------------------------------------------------------
1 | lexer grammar CWScriptLexer;
2 |
3 | // KEYWORDS
4 | DEBUG: 'debug!';
5 | CONTRACT: 'contract';
6 | INTERFACE: 'interface';
7 | IMPORT: 'import';
8 | IMPLEMENTS: 'implements';
9 | EXTENDS: 'extends';
10 | ERROR: 'error';
11 | EVENT: 'event';
12 | DEFER: 'defer';
13 | INSTANTIATE_NOW: 'instantiate!';
14 | EXEC_NOW: 'exec!';
15 | QUERY_NOW: 'query!';
16 | DELEGATE_EXEC: 'delegate_exec!';
17 | INSTANTIATE: 'instantiate';
18 | EXEC: 'exec';
19 | QUERY: 'query';
20 | REPLY: 'reply';
21 | FOR: 'for';
22 | IN: 'in';
23 | FROM: 'from';
24 | STATE: 'state';
25 | IF: 'if';
26 | IS: 'is';
27 | TRY: 'try';
28 | CATCH: 'catch';
29 | ELSE: 'else';
30 | NOT: 'not';
31 | NONE: 'None';
32 | MUT: 'mut';
33 | AND: 'and';
34 | OR: 'or';
35 | TRUE: 'true';
36 | FALSE: 'false';
37 | FN: 'fn';
38 | LET: 'let';
39 | CONST: 'const';
40 | FAIL: 'fail!';
41 | RETURN: 'return';
42 | STRUCT: 'struct';
43 | ENUM: 'enum';
44 | TYPE: 'type';
45 | EMIT: 'emit';
46 | AS: 'as';
47 |
48 |
49 | // PUNCTUATION
50 | TILDE: '~';
51 | LPAREN: '(';
52 | RPAREN: ')';
53 | LBRACK: '[';
54 | RBRACK: ']';
55 | LBRACE: '{';
56 | RBRACE: '}';
57 | DOT: '.';
58 | COMMA: ',';
59 | D_QUEST: '??';
60 | QUEST: '?';
61 | BANG: '!';
62 | SEMI: ';';
63 | COLON: ':';
64 | D_COLON: '::';
65 | HASH: '#';
66 | AT: '@';
67 | AMP: '&';
68 | ARROW: '->';
69 | FAT_ARROW: '=>';
70 | BAR: '|';
71 | S_QUOTE: '\'';
72 | D_QUOTE: '"';
73 | EQ: '='; // OPS
74 | EQ_EQ: '==';
75 | NEQ: '!=';
76 | PLUS: '+';
77 | PLUS_EQ: '+=';
78 | MINUS: '-';
79 | MINUS_EQ: '-=';
80 | MUL: '*';
81 | MUL_EQ: '*=';
82 | DIV: '/';
83 | DIV_EQ: '/=';
84 | MOD: '%';
85 | MOD_EQ: '%=';
86 | LT: '<';
87 | LT_EQ: '<=';
88 | GT: '>';
89 | GT_EQ: '>=';
90 | POW: '**';
91 |
92 | // Identifiers
93 | Ident: [_a-zA-Z$][_a-zA-Z0-9]*;
94 |
95 | // Strings
96 | StringLiteral: D_QUOTE DoubleQuotedStringCharacter* D_QUOTE;
97 | fragment DoubleQuotedStringCharacter: ~["\r\n\\] | ('\\' .);
98 |
99 | // Numbers
100 | IntLiteral: DecimalDigits;
101 | DecLiteral: (DecimalDigits? DOT DecimalDigits);
102 | fragment DecimalDigits: [0-9] ( '_'? [0-9])*;
103 |
104 | // Bool
105 | BoolLiteral: TRUE | FALSE;
106 |
107 | // Comments
108 | CWSPEC_LINE_COMMENT: ('///' .*? [\r\n])+;
109 | CWSPEC_BLOCK_COMMENT: '/**' .*? '*/';
110 |
111 | LINE_COMMENT: '//' ~[\r\n]* -> channel(HIDDEN);
112 | BLOCK_COMMENT: '/*' .*? '*/' -> channel(HIDDEN);
113 |
114 | // Whitespace
115 | WS: [\r\n\t ] -> channel(HIDDEN);
116 |
--------------------------------------------------------------------------------
/grammar/.antlr/CWScriptLexer.tokens:
--------------------------------------------------------------------------------
1 | CONTRACT=1
2 | INTERFACE=2
3 | IMPORT=3
4 | IMPLEMENTS=4
5 | EXTENDS=5
6 | ERROR=6
7 | EVENT=7
8 | INSTANTIATE_NOW=8
9 | EXEC_NOW=9
10 | QUERY_NOW=10
11 | DELEGATE_EXEC=11
12 | INSTANTIATE=12
13 | EXEC=13
14 | QUERY=14
15 | REPLY=15
16 | FOR=16
17 | IN=17
18 | FROM=18
19 | STATE=19
20 | IF=20
21 | IS=21
22 | TRY=22
23 | CATCH=23
24 | ELSE=24
25 | NOT=25
26 | NONE=26
27 | MUT=27
28 | AND=28
29 | OR=29
30 | TRUE=30
31 | FALSE=31
32 | FN=32
33 | LET=33
34 | CONST=34
35 | FAIL=35
36 | RETURN=36
37 | STRUCT=37
38 | ENUM=38
39 | TYPE=39
40 | EMIT=40
41 | AS=41
42 | TILDE=42
43 | LPAREN=43
44 | RPAREN=44
45 | LBRACK=45
46 | RBRACK=46
47 | LBRACE=47
48 | RBRACE=48
49 | DOT=49
50 | COMMA=50
51 | D_QUEST=51
52 | QUEST=52
53 | BANG=53
54 | COLON=54
55 | D_COLON=55
56 | HASH=56
57 | AT=57
58 | AMP=58
59 | ARROW=59
60 | FAT_ARROW=60
61 | BAR=61
62 | S_QUOTE=62
63 | D_QUOTE=63
64 | EQ=64
65 | EQ_EQ=65
66 | NEQ=66
67 | PLUS=67
68 | PLUS_EQ=68
69 | MINUS=69
70 | MINUS_EQ=70
71 | MUL=71
72 | MUL_EQ=72
73 | DIV=73
74 | DIV_EQ=74
75 | MOD=75
76 | MOD_EQ=76
77 | LT=77
78 | LT_EQ=78
79 | GT=79
80 | GT_EQ=80
81 | POW=81
82 | Ident=82
83 | StringLiteral=83
84 | IntLiteral=84
85 | DecLiteral=85
86 | BoolLiteral=86
87 | CWSPEC_LINE_COMMENT=87
88 | CWSPEC_BLOCK_COMMENT=88
89 | LINE_COMMENT=89
90 | BLOCK_COMMENT=90
91 | WS=91
92 | 'contract'=1
93 | 'interface'=2
94 | 'import'=3
95 | 'implements'=4
96 | 'extends'=5
97 | 'error'=6
98 | 'event'=7
99 | 'instantiate!'=8
100 | 'exec!'=9
101 | 'query!'=10
102 | 'delegate_exec!'=11
103 | 'instantiate'=12
104 | 'exec'=13
105 | 'query'=14
106 | 'reply'=15
107 | 'for'=16
108 | 'in'=17
109 | 'from'=18
110 | 'state'=19
111 | 'if'=20
112 | 'is'=21
113 | 'try'=22
114 | 'catch'=23
115 | 'else'=24
116 | 'not'=25
117 | 'None'=26
118 | 'mut'=27
119 | 'and'=28
120 | 'or'=29
121 | 'true'=30
122 | 'false'=31
123 | 'fn'=32
124 | 'let'=33
125 | 'const'=34
126 | 'fail!'=35
127 | 'return'=36
128 | 'struct'=37
129 | 'enum'=38
130 | 'type'=39
131 | 'emit'=40
132 | 'as'=41
133 | '~'=42
134 | '('=43
135 | ')'=44
136 | '['=45
137 | ']'=46
138 | '{'=47
139 | '}'=48
140 | '.'=49
141 | ','=50
142 | '??'=51
143 | '?'=52
144 | '!'=53
145 | ':'=54
146 | '::'=55
147 | '#'=56
148 | '@'=57
149 | '&'=58
150 | '->'=59
151 | '=>'=60
152 | '|'=61
153 | '\''=62
154 | '"'=63
155 | '='=64
156 | '=='=65
157 | '!='=66
158 | '+'=67
159 | '+='=68
160 | '-'=69
161 | '-='=70
162 | '*'=71
163 | '*='=72
164 | '/'=73
165 | '/='=74
166 | '%'=75
167 | '%='=76
168 | '<'=77
169 | '<='=78
170 | '>'=79
171 | '>='=80
172 | '**'=81
173 |
--------------------------------------------------------------------------------
/grammar/.antlr/CWScriptParser.tokens:
--------------------------------------------------------------------------------
1 | CONTRACT=1
2 | INTERFACE=2
3 | IMPORT=3
4 | IMPLEMENTS=4
5 | EXTENDS=5
6 | ERROR=6
7 | EVENT=7
8 | INSTANTIATE_NOW=8
9 | EXEC_NOW=9
10 | QUERY_NOW=10
11 | DELEGATE_EXEC=11
12 | INSTANTIATE=12
13 | EXEC=13
14 | QUERY=14
15 | REPLY=15
16 | FOR=16
17 | IN=17
18 | FROM=18
19 | STATE=19
20 | IF=20
21 | IS=21
22 | TRY=22
23 | CATCH=23
24 | ELSE=24
25 | NOT=25
26 | NONE=26
27 | MUT=27
28 | AND=28
29 | OR=29
30 | TRUE=30
31 | FALSE=31
32 | FN=32
33 | LET=33
34 | CONST=34
35 | FAIL=35
36 | RETURN=36
37 | STRUCT=37
38 | ENUM=38
39 | TYPE=39
40 | EMIT=40
41 | AS=41
42 | TILDE=42
43 | LPAREN=43
44 | RPAREN=44
45 | LBRACK=45
46 | RBRACK=46
47 | LBRACE=47
48 | RBRACE=48
49 | DOT=49
50 | COMMA=50
51 | D_QUEST=51
52 | QUEST=52
53 | BANG=53
54 | COLON=54
55 | D_COLON=55
56 | HASH=56
57 | AT=57
58 | AMP=58
59 | ARROW=59
60 | FAT_ARROW=60
61 | BAR=61
62 | S_QUOTE=62
63 | D_QUOTE=63
64 | EQ=64
65 | EQ_EQ=65
66 | NEQ=66
67 | PLUS=67
68 | PLUS_EQ=68
69 | MINUS=69
70 | MINUS_EQ=70
71 | MUL=71
72 | MUL_EQ=72
73 | DIV=73
74 | DIV_EQ=74
75 | MOD=75
76 | MOD_EQ=76
77 | LT=77
78 | LT_EQ=78
79 | GT=79
80 | GT_EQ=80
81 | POW=81
82 | Ident=82
83 | StringLiteral=83
84 | IntLiteral=84
85 | DecLiteral=85
86 | BoolLiteral=86
87 | CWSPEC_LINE_COMMENT=87
88 | CWSPEC_BLOCK_COMMENT=88
89 | LINE_COMMENT=89
90 | BLOCK_COMMENT=90
91 | WS=91
92 | 'contract'=1
93 | 'interface'=2
94 | 'import'=3
95 | 'implements'=4
96 | 'extends'=5
97 | 'error'=6
98 | 'event'=7
99 | 'instantiate!'=8
100 | 'exec!'=9
101 | 'query!'=10
102 | 'delegate_exec!'=11
103 | 'instantiate'=12
104 | 'exec'=13
105 | 'query'=14
106 | 'reply'=15
107 | 'for'=16
108 | 'in'=17
109 | 'from'=18
110 | 'state'=19
111 | 'if'=20
112 | 'is'=21
113 | 'try'=22
114 | 'catch'=23
115 | 'else'=24
116 | 'not'=25
117 | 'None'=26
118 | 'mut'=27
119 | 'and'=28
120 | 'or'=29
121 | 'true'=30
122 | 'false'=31
123 | 'fn'=32
124 | 'let'=33
125 | 'const'=34
126 | 'fail!'=35
127 | 'return'=36
128 | 'struct'=37
129 | 'enum'=38
130 | 'type'=39
131 | 'emit'=40
132 | 'as'=41
133 | '~'=42
134 | '('=43
135 | ')'=44
136 | '['=45
137 | ']'=46
138 | '{'=47
139 | '}'=48
140 | '.'=49
141 | ','=50
142 | '??'=51
143 | '?'=52
144 | '!'=53
145 | ':'=54
146 | '::'=55
147 | '#'=56
148 | '@'=57
149 | '&'=58
150 | '->'=59
151 | '=>'=60
152 | '|'=61
153 | '\''=62
154 | '"'=63
155 | '='=64
156 | '=='=65
157 | '!='=66
158 | '+'=67
159 | '+='=68
160 | '-'=69
161 | '-='=70
162 | '*'=71
163 | '*='=72
164 | '/'=73
165 | '/='=74
166 | '%'=75
167 | '%='=76
168 | '<'=77
169 | '<='=78
170 | '>'=79
171 | '>='=80
172 | '**'=81
173 |
--------------------------------------------------------------------------------
/grammar/CWScriptLexer.tokens:
--------------------------------------------------------------------------------
1 | DEBUG=1
2 | CONTRACT=2
3 | INTERFACE=3
4 | IMPORT=4
5 | IMPLEMENTS=5
6 | EXTENDS=6
7 | ERROR=7
8 | EVENT=8
9 | INSTANTIATE_NOW=9
10 | EXEC_NOW=10
11 | QUERY_NOW=11
12 | DELEGATE_EXEC=12
13 | INSTANTIATE=13
14 | EXEC=14
15 | QUERY=15
16 | REPLY=16
17 | FOR=17
18 | IN=18
19 | FROM=19
20 | STATE=20
21 | IF=21
22 | IS=22
23 | TRY=23
24 | CATCH=24
25 | ELSE=25
26 | NOT=26
27 | NONE=27
28 | MUT=28
29 | AND=29
30 | OR=30
31 | TRUE=31
32 | FALSE=32
33 | FN=33
34 | LET=34
35 | CONST=35
36 | FAIL=36
37 | RETURN=37
38 | STRUCT=38
39 | ENUM=39
40 | TYPE=40
41 | EMIT=41
42 | AS=42
43 | TILDE=43
44 | LPAREN=44
45 | RPAREN=45
46 | LBRACK=46
47 | RBRACK=47
48 | LBRACE=48
49 | RBRACE=49
50 | DOT=50
51 | COMMA=51
52 | D_QUEST=52
53 | QUEST=53
54 | BANG=54
55 | SEMI=55
56 | COLON=56
57 | D_COLON=57
58 | HASH=58
59 | AT=59
60 | AMP=60
61 | ARROW=61
62 | FAT_ARROW=62
63 | BAR=63
64 | S_QUOTE=64
65 | D_QUOTE=65
66 | EQ=66
67 | EQ_EQ=67
68 | NEQ=68
69 | PLUS=69
70 | PLUS_EQ=70
71 | MINUS=71
72 | MINUS_EQ=72
73 | MUL=73
74 | MUL_EQ=74
75 | DIV=75
76 | DIV_EQ=76
77 | MOD=77
78 | MOD_EQ=78
79 | LT=79
80 | LT_EQ=80
81 | GT=81
82 | GT_EQ=82
83 | POW=83
84 | Ident=84
85 | StringLiteral=85
86 | IntLiteral=86
87 | DecLiteral=87
88 | BoolLiteral=88
89 | CWSPEC_LINE_COMMENT=89
90 | CWSPEC_BLOCK_COMMENT=90
91 | LINE_COMMENT=91
92 | BLOCK_COMMENT=92
93 | WS=93
94 | 'debug!'=1
95 | 'contract'=2
96 | 'interface'=3
97 | 'import'=4
98 | 'implements'=5
99 | 'extends'=6
100 | 'error'=7
101 | 'event'=8
102 | 'instantiate!'=9
103 | 'exec!'=10
104 | 'query!'=11
105 | 'delegate_exec!'=12
106 | 'instantiate'=13
107 | 'exec'=14
108 | 'query'=15
109 | 'reply'=16
110 | 'for'=17
111 | 'in'=18
112 | 'from'=19
113 | 'state'=20
114 | 'if'=21
115 | 'is'=22
116 | 'try'=23
117 | 'catch'=24
118 | 'else'=25
119 | 'not'=26
120 | 'None'=27
121 | 'mut'=28
122 | 'and'=29
123 | 'or'=30
124 | 'true'=31
125 | 'false'=32
126 | 'fn'=33
127 | 'let'=34
128 | 'const'=35
129 | 'fail!'=36
130 | 'return'=37
131 | 'struct'=38
132 | 'enum'=39
133 | 'type'=40
134 | 'emit'=41
135 | 'as'=42
136 | '~'=43
137 | '('=44
138 | ')'=45
139 | '['=46
140 | ']'=47
141 | '{'=48
142 | '}'=49
143 | '.'=50
144 | ','=51
145 | '??'=52
146 | '?'=53
147 | '!'=54
148 | ';'=55
149 | ':'=56
150 | '::'=57
151 | '#'=58
152 | '@'=59
153 | '&'=60
154 | '->'=61
155 | '=>'=62
156 | '|'=63
157 | '\''=64
158 | '"'=65
159 | '='=66
160 | '=='=67
161 | '!='=68
162 | '+'=69
163 | '+='=70
164 | '-'=71
165 | '-='=72
166 | '*'=73
167 | '*='=74
168 | '/'=75
169 | '/='=76
170 | '%'=77
171 | '%='=78
172 | '<'=79
173 | '<='=80
174 | '>'=81
175 | '>='=82
176 | '**'=83
177 |
--------------------------------------------------------------------------------
/grammar/gen/CWScriptLexer.tokens:
--------------------------------------------------------------------------------
1 | DEBUG=1
2 | CONTRACT=2
3 | INTERFACE=3
4 | IMPORT=4
5 | IMPLEMENTS=5
6 | EXTENDS=6
7 | ERROR=7
8 | EVENT=8
9 | INSTANTIATE_NOW=9
10 | EXEC_NOW=10
11 | QUERY_NOW=11
12 | DELEGATE_EXEC=12
13 | INSTANTIATE=13
14 | EXEC=14
15 | QUERY=15
16 | REPLY=16
17 | FOR=17
18 | IN=18
19 | FROM=19
20 | STATE=20
21 | IF=21
22 | IS=22
23 | TRY=23
24 | CATCH=24
25 | ELSE=25
26 | NOT=26
27 | NONE=27
28 | MUT=28
29 | AND=29
30 | OR=30
31 | TRUE=31
32 | FALSE=32
33 | FN=33
34 | LET=34
35 | CONST=35
36 | FAIL=36
37 | RETURN=37
38 | STRUCT=38
39 | ENUM=39
40 | TYPE=40
41 | EMIT=41
42 | AS=42
43 | TILDE=43
44 | LPAREN=44
45 | RPAREN=45
46 | LBRACK=46
47 | RBRACK=47
48 | LBRACE=48
49 | RBRACE=49
50 | DOT=50
51 | COMMA=51
52 | D_QUEST=52
53 | QUEST=53
54 | BANG=54
55 | SEMI=55
56 | COLON=56
57 | D_COLON=57
58 | HASH=58
59 | AT=59
60 | AMP=60
61 | ARROW=61
62 | FAT_ARROW=62
63 | BAR=63
64 | S_QUOTE=64
65 | D_QUOTE=65
66 | EQ=66
67 | EQ_EQ=67
68 | NEQ=68
69 | PLUS=69
70 | PLUS_EQ=70
71 | MINUS=71
72 | MINUS_EQ=72
73 | MUL=73
74 | MUL_EQ=74
75 | DIV=75
76 | DIV_EQ=76
77 | MOD=77
78 | MOD_EQ=78
79 | LT=79
80 | LT_EQ=80
81 | GT=81
82 | GT_EQ=82
83 | POW=83
84 | Ident=84
85 | StringLiteral=85
86 | IntLiteral=86
87 | DecLiteral=87
88 | BoolLiteral=88
89 | CWSPEC_LINE_COMMENT=89
90 | CWSPEC_BLOCK_COMMENT=90
91 | LINE_COMMENT=91
92 | BLOCK_COMMENT=92
93 | WS=93
94 | 'debug!'=1
95 | 'contract'=2
96 | 'interface'=3
97 | 'import'=4
98 | 'implements'=5
99 | 'extends'=6
100 | 'error'=7
101 | 'event'=8
102 | 'instantiate!'=9
103 | 'exec!'=10
104 | 'query!'=11
105 | 'delegate_exec!'=12
106 | 'instantiate'=13
107 | 'exec'=14
108 | 'query'=15
109 | 'reply'=16
110 | 'for'=17
111 | 'in'=18
112 | 'from'=19
113 | 'state'=20
114 | 'if'=21
115 | 'is'=22
116 | 'try'=23
117 | 'catch'=24
118 | 'else'=25
119 | 'not'=26
120 | 'None'=27
121 | 'mut'=28
122 | 'and'=29
123 | 'or'=30
124 | 'true'=31
125 | 'false'=32
126 | 'fn'=33
127 | 'let'=34
128 | 'const'=35
129 | 'fail!'=36
130 | 'return'=37
131 | 'struct'=38
132 | 'enum'=39
133 | 'type'=40
134 | 'emit'=41
135 | 'as'=42
136 | '~'=43
137 | '('=44
138 | ')'=45
139 | '['=46
140 | ']'=47
141 | '{'=48
142 | '}'=49
143 | '.'=50
144 | ','=51
145 | '??'=52
146 | '?'=53
147 | '!'=54
148 | ';'=55
149 | ':'=56
150 | '::'=57
151 | '#'=58
152 | '@'=59
153 | '&'=60
154 | '->'=61
155 | '=>'=62
156 | '|'=63
157 | '\''=64
158 | '"'=65
159 | '='=66
160 | '=='=67
161 | '!='=68
162 | '+'=69
163 | '+='=70
164 | '-'=71
165 | '-='=72
166 | '*'=73
167 | '*='=74
168 | '/'=75
169 | '/='=76
170 | '%'=77
171 | '%='=78
172 | '<'=79
173 | '<='=80
174 | '>'=81
175 | '>='=82
176 | '**'=83
177 |
--------------------------------------------------------------------------------
/gen/CWScriptLexer.tokens:
--------------------------------------------------------------------------------
1 | DEBUG=1
2 | CONTRACT=2
3 | INTERFACE=3
4 | IMPORT=4
5 | IMPLEMENTS=5
6 | EXTENDS=6
7 | ERROR=7
8 | EVENT=8
9 | DEFER=9
10 | INSTANTIATE_NOW=10
11 | EXEC_NOW=11
12 | QUERY_NOW=12
13 | DELEGATE_EXEC=13
14 | INSTANTIATE=14
15 | EXEC=15
16 | QUERY=16
17 | REPLY=17
18 | FOR=18
19 | IN=19
20 | FROM=20
21 | STATE=21
22 | IF=22
23 | IS=23
24 | TRY=24
25 | CATCH=25
26 | ELSE=26
27 | NOT=27
28 | NONE=28
29 | MUT=29
30 | AND=30
31 | OR=31
32 | TRUE=32
33 | FALSE=33
34 | FN=34
35 | LET=35
36 | CONST=36
37 | FAIL=37
38 | RETURN=38
39 | STRUCT=39
40 | ENUM=40
41 | TYPE=41
42 | EMIT=42
43 | AS=43
44 | TILDE=44
45 | LPAREN=45
46 | RPAREN=46
47 | LBRACK=47
48 | RBRACK=48
49 | LBRACE=49
50 | RBRACE=50
51 | DOT=51
52 | COMMA=52
53 | D_QUEST=53
54 | QUEST=54
55 | BANG=55
56 | SEMI=56
57 | COLON=57
58 | D_COLON=58
59 | HASH=59
60 | AT=60
61 | AMP=61
62 | ARROW=62
63 | FAT_ARROW=63
64 | BAR=64
65 | S_QUOTE=65
66 | D_QUOTE=66
67 | EQ=67
68 | EQ_EQ=68
69 | NEQ=69
70 | PLUS=70
71 | PLUS_EQ=71
72 | MINUS=72
73 | MINUS_EQ=73
74 | MUL=74
75 | MUL_EQ=75
76 | DIV=76
77 | DIV_EQ=77
78 | MOD=78
79 | MOD_EQ=79
80 | LT=80
81 | LT_EQ=81
82 | GT=82
83 | GT_EQ=83
84 | POW=84
85 | Ident=85
86 | StringLiteral=86
87 | IntLiteral=87
88 | DecLiteral=88
89 | BoolLiteral=89
90 | CWSPEC_LINE_COMMENT=90
91 | CWSPEC_BLOCK_COMMENT=91
92 | LINE_COMMENT=92
93 | BLOCK_COMMENT=93
94 | WS=94
95 | 'debug!'=1
96 | 'contract'=2
97 | 'interface'=3
98 | 'import'=4
99 | 'implements'=5
100 | 'extends'=6
101 | 'error'=7
102 | 'event'=8
103 | 'defer'=9
104 | 'instantiate!'=10
105 | 'exec!'=11
106 | 'query!'=12
107 | 'delegate_exec!'=13
108 | 'instantiate'=14
109 | 'exec'=15
110 | 'query'=16
111 | 'reply'=17
112 | 'for'=18
113 | 'in'=19
114 | 'from'=20
115 | 'state'=21
116 | 'if'=22
117 | 'is'=23
118 | 'try'=24
119 | 'catch'=25
120 | 'else'=26
121 | 'not'=27
122 | 'None'=28
123 | 'mut'=29
124 | 'and'=30
125 | 'or'=31
126 | 'true'=32
127 | 'false'=33
128 | 'fn'=34
129 | 'let'=35
130 | 'const'=36
131 | 'fail!'=37
132 | 'return'=38
133 | 'struct'=39
134 | 'enum'=40
135 | 'type'=41
136 | 'emit'=42
137 | 'as'=43
138 | '~'=44
139 | '('=45
140 | ')'=46
141 | '['=47
142 | ']'=48
143 | '{'=49
144 | '}'=50
145 | '.'=51
146 | ','=52
147 | '??'=53
148 | '?'=54
149 | '!'=55
150 | ';'=56
151 | ':'=57
152 | '::'=58
153 | '#'=59
154 | '@'=60
155 | '&'=61
156 | '->'=62
157 | '=>'=63
158 | '|'=64
159 | '\''=65
160 | '"'=66
161 | '='=67
162 | '=='=68
163 | '!='=69
164 | '+'=70
165 | '+='=71
166 | '-'=72
167 | '-='=73
168 | '*'=74
169 | '*='=75
170 | '/'=76
171 | '/='=77
172 | '%'=78
173 | '%='=79
174 | '<'=80
175 | '<='=81
176 | '>'=82
177 | '>='=83
178 | '**'=84
179 |
--------------------------------------------------------------------------------
/src/grammar/CWScriptLexer.tokens:
--------------------------------------------------------------------------------
1 | DEBUG=1
2 | CONTRACT=2
3 | INTERFACE=3
4 | IMPORT=4
5 | IMPLEMENTS=5
6 | EXTENDS=6
7 | ERROR=7
8 | EVENT=8
9 | DEFER=9
10 | INSTANTIATE_NOW=10
11 | EXEC_NOW=11
12 | QUERY_NOW=12
13 | DELEGATE_EXEC=13
14 | INSTANTIATE=14
15 | EXEC=15
16 | QUERY=16
17 | REPLY=17
18 | FOR=18
19 | IN=19
20 | FROM=20
21 | STATE=21
22 | IF=22
23 | IS=23
24 | TRY=24
25 | CATCH=25
26 | ELSE=26
27 | NOT=27
28 | NONE=28
29 | MUT=29
30 | AND=30
31 | OR=31
32 | TRUE=32
33 | FALSE=33
34 | FN=34
35 | LET=35
36 | CONST=36
37 | FAIL=37
38 | RETURN=38
39 | STRUCT=39
40 | ENUM=40
41 | TYPE=41
42 | EMIT=42
43 | AS=43
44 | TILDE=44
45 | LPAREN=45
46 | RPAREN=46
47 | LBRACK=47
48 | RBRACK=48
49 | LBRACE=49
50 | RBRACE=50
51 | DOT=51
52 | COMMA=52
53 | D_QUEST=53
54 | QUEST=54
55 | BANG=55
56 | SEMI=56
57 | COLON=57
58 | D_COLON=58
59 | HASH=59
60 | AT=60
61 | AMP=61
62 | ARROW=62
63 | FAT_ARROW=63
64 | BAR=64
65 | S_QUOTE=65
66 | D_QUOTE=66
67 | EQ=67
68 | EQ_EQ=68
69 | NEQ=69
70 | PLUS=70
71 | PLUS_EQ=71
72 | MINUS=72
73 | MINUS_EQ=73
74 | MUL=74
75 | MUL_EQ=75
76 | DIV=76
77 | DIV_EQ=77
78 | MOD=78
79 | MOD_EQ=79
80 | LT=80
81 | LT_EQ=81
82 | GT=82
83 | GT_EQ=83
84 | POW=84
85 | Ident=85
86 | StringLiteral=86
87 | IntLiteral=87
88 | DecLiteral=88
89 | BoolLiteral=89
90 | CWSPEC_LINE_COMMENT=90
91 | CWSPEC_BLOCK_COMMENT=91
92 | LINE_COMMENT=92
93 | BLOCK_COMMENT=93
94 | WS=94
95 | 'debug!'=1
96 | 'contract'=2
97 | 'interface'=3
98 | 'import'=4
99 | 'implements'=5
100 | 'extends'=6
101 | 'error'=7
102 | 'event'=8
103 | 'defer'=9
104 | 'instantiate!'=10
105 | 'exec!'=11
106 | 'query!'=12
107 | 'delegate_exec!'=13
108 | 'instantiate'=14
109 | 'exec'=15
110 | 'query'=16
111 | 'reply'=17
112 | 'for'=18
113 | 'in'=19
114 | 'from'=20
115 | 'state'=21
116 | 'if'=22
117 | 'is'=23
118 | 'try'=24
119 | 'catch'=25
120 | 'else'=26
121 | 'not'=27
122 | 'None'=28
123 | 'mut'=29
124 | 'and'=30
125 | 'or'=31
126 | 'true'=32
127 | 'false'=33
128 | 'fn'=34
129 | 'let'=35
130 | 'const'=36
131 | 'fail!'=37
132 | 'return'=38
133 | 'struct'=39
134 | 'enum'=40
135 | 'type'=41
136 | 'emit'=42
137 | 'as'=43
138 | '~'=44
139 | '('=45
140 | ')'=46
141 | '['=47
142 | ']'=48
143 | '{'=49
144 | '}'=50
145 | '.'=51
146 | ','=52
147 | '??'=53
148 | '?'=54
149 | '!'=55
150 | ';'=56
151 | ':'=57
152 | '::'=58
153 | '#'=59
154 | '@'=60
155 | '&'=61
156 | '->'=62
157 | '=>'=63
158 | '|'=64
159 | '\''=65
160 | '"'=66
161 | '='=67
162 | '=='=68
163 | '!='=69
164 | '+'=70
165 | '+='=71
166 | '-'=72
167 | '-='=73
168 | '*'=74
169 | '*='=75
170 | '/'=76
171 | '/='=77
172 | '%'=78
173 | '%='=79
174 | '<'=80
175 | '<='=81
176 | '>'=82
177 | '>='=83
178 | '**'=84
179 |
--------------------------------------------------------------------------------
/src/grammar/CWScriptParser.tokens:
--------------------------------------------------------------------------------
1 | DEBUG=1
2 | CONTRACT=2
3 | INTERFACE=3
4 | IMPORT=4
5 | IMPLEMENTS=5
6 | EXTENDS=6
7 | ERROR=7
8 | EVENT=8
9 | DEFER=9
10 | INSTANTIATE_NOW=10
11 | EXEC_NOW=11
12 | QUERY_NOW=12
13 | DELEGATE_EXEC=13
14 | INSTANTIATE=14
15 | EXEC=15
16 | QUERY=16
17 | REPLY=17
18 | FOR=18
19 | IN=19
20 | FROM=20
21 | STATE=21
22 | IF=22
23 | IS=23
24 | TRY=24
25 | CATCH=25
26 | ELSE=26
27 | NOT=27
28 | NONE=28
29 | MUT=29
30 | AND=30
31 | OR=31
32 | TRUE=32
33 | FALSE=33
34 | FN=34
35 | LET=35
36 | CONST=36
37 | FAIL=37
38 | RETURN=38
39 | STRUCT=39
40 | ENUM=40
41 | TYPE=41
42 | EMIT=42
43 | AS=43
44 | TILDE=44
45 | LPAREN=45
46 | RPAREN=46
47 | LBRACK=47
48 | RBRACK=48
49 | LBRACE=49
50 | RBRACE=50
51 | DOT=51
52 | COMMA=52
53 | D_QUEST=53
54 | QUEST=54
55 | BANG=55
56 | SEMI=56
57 | COLON=57
58 | D_COLON=58
59 | HASH=59
60 | AT=60
61 | AMP=61
62 | ARROW=62
63 | FAT_ARROW=63
64 | BAR=64
65 | S_QUOTE=65
66 | D_QUOTE=66
67 | EQ=67
68 | EQ_EQ=68
69 | NEQ=69
70 | PLUS=70
71 | PLUS_EQ=71
72 | MINUS=72
73 | MINUS_EQ=73
74 | MUL=74
75 | MUL_EQ=75
76 | DIV=76
77 | DIV_EQ=77
78 | MOD=78
79 | MOD_EQ=79
80 | LT=80
81 | LT_EQ=81
82 | GT=82
83 | GT_EQ=83
84 | POW=84
85 | Ident=85
86 | StringLiteral=86
87 | IntLiteral=87
88 | DecLiteral=88
89 | BoolLiteral=89
90 | CWSPEC_LINE_COMMENT=90
91 | CWSPEC_BLOCK_COMMENT=91
92 | LINE_COMMENT=92
93 | BLOCK_COMMENT=93
94 | WS=94
95 | 'debug!'=1
96 | 'contract'=2
97 | 'interface'=3
98 | 'import'=4
99 | 'implements'=5
100 | 'extends'=6
101 | 'error'=7
102 | 'event'=8
103 | 'defer'=9
104 | 'instantiate!'=10
105 | 'exec!'=11
106 | 'query!'=12
107 | 'delegate_exec!'=13
108 | 'instantiate'=14
109 | 'exec'=15
110 | 'query'=16
111 | 'reply'=17
112 | 'for'=18
113 | 'in'=19
114 | 'from'=20
115 | 'state'=21
116 | 'if'=22
117 | 'is'=23
118 | 'try'=24
119 | 'catch'=25
120 | 'else'=26
121 | 'not'=27
122 | 'None'=28
123 | 'mut'=29
124 | 'and'=30
125 | 'or'=31
126 | 'true'=32
127 | 'false'=33
128 | 'fn'=34
129 | 'let'=35
130 | 'const'=36
131 | 'fail!'=37
132 | 'return'=38
133 | 'struct'=39
134 | 'enum'=40
135 | 'type'=41
136 | 'emit'=42
137 | 'as'=43
138 | '~'=44
139 | '('=45
140 | ')'=46
141 | '['=47
142 | ']'=48
143 | '{'=49
144 | '}'=50
145 | '.'=51
146 | ','=52
147 | '??'=53
148 | '?'=54
149 | '!'=55
150 | ';'=56
151 | ':'=57
152 | '::'=58
153 | '#'=59
154 | '@'=60
155 | '&'=61
156 | '->'=62
157 | '=>'=63
158 | '|'=64
159 | '\''=65
160 | '"'=66
161 | '='=67
162 | '=='=68
163 | '!='=69
164 | '+'=70
165 | '+='=71
166 | '-'=72
167 | '-='=73
168 | '*'=74
169 | '*='=75
170 | '/'=76
171 | '/='=77
172 | '%'=78
173 | '%='=79
174 | '<'=80
175 | '<='=81
176 | '>'=82
177 | '>='=83
178 | '**'=84
179 |
--------------------------------------------------------------------------------
/__tests__/interpreter/TerraswapToken.test.ts:
--------------------------------------------------------------------------------
1 | import { ContractInstance, CWSInterpreter, Env } from '../../src/interpreter';
2 | import {
3 | ContractDefn,
4 | ContractReference,
5 | CWSString,
6 | STDLIB,
7 | StringT,
8 | AddressT,
9 | None,
10 | U8_T,
11 | U128_T,
12 | IntT,
13 | args,
14 | InterfaceDefn,
15 | StructDefn,
16 | ListT,
17 | FnDefn,
18 | } from '../../src/stdlib';
19 | import * as fs from 'fs';
20 |
21 | const EXAMPLES_DIR = __dirname + '/../../examples';
22 | const TERRASWAP_TOKEN_FILE = EXAMPLES_DIR + '/terraswap/TerraswapToken.cws';
23 |
24 | describe('Interpreter: TerraswapToken', () => {
25 | it('should be able to parse and interpret a TerraswapToken contract', () => {
26 | const sourceText = fs.readFileSync(TERRASWAP_TOKEN_FILE, 'utf8');
27 |
28 | const interpreter = new CWSInterpreter({
29 | sources: {
30 | [TERRASWAP_TOKEN_FILE]: sourceText,
31 | },
32 | env: STDLIB,
33 | });
34 |
35 | let TerraswapToken = interpreter.getSymbol('TerraswapToken');
36 | let CW20 = interpreter.getSymbol('CW20');
37 | let Coin = CW20.getSymbol('Coin');
38 | let CoinList = new ListT(Coin);
39 |
40 | let myAddress = CWSString.TYPE.value(
41 | 'terra1hzh9vpxhsk82503se0vv5jj6etdvxu3nv8z07e'
42 | );
43 | let instantiateArgs = args([], {
44 | name: StringT.value('Terran One Token'),
45 | symbol: StringT.value('TONE'),
46 | decimals: U8_T.value(6),
47 | initial_balances: CoinList.value([
48 | Coin.value(args([StringT.value('yogesh'), U128_T.value('1000000000')])),
49 | Coin.value(
50 | args([StringT.value('william'), U128_T.value('1000000000')])
51 | ),
52 | ]),
53 | });
54 | let instantiateMsg = TerraswapToken.instantiate(instantiateArgs);
55 | // call the instantiate implementation
56 |
57 | let env: Env = {
58 | block: {
59 | height: 1,
60 | time: 1,
61 | chain_id: 'terran-1',
62 | },
63 | contract: {
64 | address: 't1tokenaddr',
65 | },
66 | };
67 |
68 | let info = {
69 | sender: 'william',
70 | funds: [
71 | {
72 | amount: '1000000000',
73 | denom: 'utone',
74 | },
75 | ],
76 | };
77 |
78 | let myToken = new ContractInstance(interpreter, TerraswapToken);
79 | let res = myToken.instantiate(env, info, instantiateArgs);
80 | let res2 = myToken.exec(
81 | env,
82 | info,
83 | 'transfer',
84 | args([], {
85 | recipient: StringT.value('yogesh'),
86 | amount: U128_T.value('5000000'),
87 | })
88 | );
89 | console.log(res2);
90 | myToken.state;
91 | expect(TerraswapToken).toBeInstanceOf(ContractDefn);
92 | });
93 | });
94 |
--------------------------------------------------------------------------------
/.idea/codeStyles/Project.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
--------------------------------------------------------------------------------
/dist/parser/validation.js.map:
--------------------------------------------------------------------------------
1 | {"version":3,"file":"validation.js","sourceRoot":"","sources":["../../src/parser/validation.ts"],"names":[],"mappings":"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"}
--------------------------------------------------------------------------------
/examples/atomic-order-example/AtomicOrderExample.cws:
--------------------------------------------------------------------------------
1 | import { SubaccountId, MarketId } from "injective/types"
2 | import { FPDecimal } from "injective/math"
3 | import { CW2 } from "standards/cw2"
4 |
5 | const CONTRACT_NAME = "crates.io:atomic-order-example"
6 | const CONTRACT_VERSION = "0.0.1"
7 |
8 | contract AtomicOrderExample extends CW2 {
9 |
10 | state {
11 | config: struct ContractConfigState {
12 | market_id: MarketId,
13 | owner: Address,
14 | contract_subaccount_id: SubaccountId,
15 | base_denom: String,
16 | quote_denom: String
17 | }
18 | swap_operation_state: struct SwapCacheState {
19 | sender_address: String,
20 | deposited_amount: Coin
21 | }
22 | }
23 |
24 | #instantiate(
25 | market_id: MarketId
26 | ) {
27 |
28 | let market = try {
29 | query! Exchange.#market(market_id)
30 | } else fail! "Market with id: {market_id} not found"
31 |
32 | let config = ContractConfigState {
33 | market_id,
34 | base_denom: market.base_denom,
35 | quote_denom: market.quote_denom,
36 | owner: $info.sender,
37 | contract_subaccount_id: SubaccountId($env.contract.address, 0),
38 | }
39 |
40 | CW2.set_contract_version!($, CONTRACT_NAME, CONTRACT_VERSION)
41 |
42 | // we've changed it to "config"
43 | $state.config = config
44 | emit event(method="instantiate", owner=$info.sender) // anonymous event
45 | }
46 |
47 | reply.success handle_atomic_order() {
48 | let dec_scale_factor = FPDecimal(1000000000000000000)
49 | let order_response = Exchange.#create_spot_market_order::parse_response!($data)
50 |
51 | let trade_data = order_response.results ?? fail! "No trade data in order response"
52 | let quantity = FPDecimal!(trade_data.quantity)
53 | let price = FPDecimal!(trade_data.price)
54 | let fee = FPDecimal!(trade_data.fee)
55 |
56 | let { config, cache } = $state
57 | let contract_address = $env.contract.address
58 | let subaccount_id = config.contract_subaccount_id
59 | let cache = $state.cache
60 | let purchased_coins = coin(quantity, config.base_denom)
61 | let pair = quantity * price + fee
62 | let leftover = cache.deposited_amount.amount - paid
63 |
64 |
65 | exec! Exchange.#withdraw(contract_address, subaccount_id, purchased_coins)
66 | exec! Exchange.#withdraw(contract_address, subaccount_id, leftover_coins)
67 | exec! Bank.#send(cache.sender_address, [purchased_coins, leftover_coins])
68 | }
69 |
70 | exec #swap_spot(quantity: FPDecimal, price: FPDecimal) {
71 | let { config } = $state
72 | let contract = $env.contract.address
73 | let subaccount_id = config.contract_subaccount_id
74 | let min_deposit = price quantity
75 |
76 | if $info.funds.is_empty() {
77 | fail! "No funds deposited!"
78 | }
79 |
80 | let message_deposit = FPDecimal!($info.funds[0].amount)
81 |
82 | if message_deposit < min_deposit {
83 | fail! "Deposit: {message_deposit} below min_deposit: {min_deposit}"
84 | }
85 |
86 | let order = SpotOrder(
87 | price, quantity, OrderType.#BuyAtomic, config.market_id, subaccount_id, contract
88 | )
89 |
90 | let coins = $info.funds[0]
91 |
92 | $state.swap_operation_state = SwapCacheState($info.sender, coins)
93 |
94 | exec! Exchange.#deposit(contract, subaccount_id, coins)
95 |
96 | @reply.success(handle_atomic_order)
97 | exec! Exchange.create_spot_market_order(contract, order)
98 | }
99 |
100 | }
101 |
--------------------------------------------------------------------------------
/dist/parser/index.js.map:
--------------------------------------------------------------------------------
1 | {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/parser/index.ts"],"names":[],"mappings":";;;;;;AAAA,cAAc;AACd,uCAA8E;AAC9E,4DAA+E;AAC/E,8DAGmC;AACnC,uCAAiD;AAEjD,+CAA4C;AAC5C,iEAAuE;AAEvE,gDAAwB;AAMxB,MAAsB,uBAAuB;IAA7C;QACS,gBAAW,GAAiB,EAAE,CAAC;IAyBxC,CAAC;IAvBC,IAAW,MAAM;QACf,OAAO,IAAI,CAAC,WAAW,CAAC,MAAM,CAC5B,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,QAAQ,KAAK,0CAAkB,CAAC,KAAK,CAC/C,CAAC;IACJ,CAAC;IAED,IAAW,QAAQ;QACjB,OAAO,IAAI,CAAC,WAAW,CAAC,MAAM,CAC5B,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,QAAQ,KAAK,0CAAkB,CAAC,OAAO,CACjD,CAAC;IACJ,CAAC;IAED,IAAW,KAAK;QACd,OAAO,IAAI,CAAC,WAAW,CAAC,MAAM,CAC5B,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,QAAQ,KAAK,0CAAkB,CAAC,WAAW,CACrD,CAAC;IACJ,CAAC;IAED,IAAW,KAAK;QACd,OAAO,IAAI,CAAC,WAAW,CAAC,MAAM,CAC5B,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,QAAQ,KAAK,0CAAkB,CAAC,IAAI,CAC9C,CAAC;IACJ,CAAC;CACF;AA1BD,0DA0BC;AAED,MAAa,sBAAsB;IACjC,YAAmB,MAAiB;QAAjB,WAAM,GAAN,MAAM,CAAW;IAAG,CAAC;IAExC,WAAW,CACT,UAAe,EACf,eAAoB,EACpB,IAAY,EACZ,kBAA0B,EAC1B,GAAW,EACX,CAAmC;QAEnC,IAAI,CAAC,MAAM,CAAC,WAAW,CAAC,IAAI,CAAC;YAC3B,QAAQ,EAAE,0CAAkB,CAAC,KAAK;YAClC,OAAO,EAAE,eAAe,GAAG,GAAG;YAC9B,KAAK,EAAE;gBACL,KAAK,EAAE,EAAE,IAAI,EAAE,IAAI,GAAG,CAAC,EAAE,SAAS,EAAE,kBAAkB,EAAE;gBACxD,GAAG,EAAE,EAAE,IAAI,EAAE,IAAI,GAAG,CAAC,EAAE,SAAS,EAAE,kBAAkB,GAAG,CAAC,EAAE;aAC3D;SACF,CAAC,CAAC;IACL,CAAC;CACF;AApBD,wDAoBC;AAED,MAAa,6BAA6B;IAGxC,IAAI,KAAK;QACP,OAAO,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;IAC7C,CAAC;IAED,YAAmB,MAAiB;QAAjB,WAAM,GAAN,MAAM,CAAW;QAN7B,WAAM,GAAQ,CAAC,EAAE,CAAC,CAAC;IAMa,CAAC;IAExC,cAAc,CAAC,GAAuB;QACpC,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,KAAK,EAAE,CAAC,IAAI,CAAC,EAAE;YACjC,IAAI,CAAC,MAAM,CAAC,WAAW,CAAC,IAAI,CAAC;gBAC3B,OAAO,EAAE,WAAW,GAAG,CAAC,KAAK,EAAE,CAAC,IAAI,mBAAmB;gBACvD,KAAK,EAAE,IAAI,CAAC,GAAG,CAAC,UAAU,CAAC,gBAAgB,CAAC,GAAG,CAAC;gBAChD,QAAQ,EAAE,0CAAkB,CAAC,KAAK;aACnC,CAAC,CAAC;SACJ;IACH,CAAC;IAED,oBAAoB;IACpB,kBAAkB,CAAC,GAA2B;QAC5C,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,GAAG,EAAE,CAAC;IAClC,CAAC;IAED,oBAAoB,CAAC,GAA6B;QAChD,GAAG,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,GAAG,EAAE,EAAE;YACzB,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,GAAG,EAAE,CAAC;QAC5B,CAAC,CAAC,CAAC;IACL,CAAC;IAED,UAAU,CAAC,GAAmB;QAC5B,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,GAAG,EAAE,CAAC;IAClC,CAAC;IAED,oBAAoB,CAAC,GAA6B;QAChD,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,GAAG,EAAE,CAAC;IAClC,CAAC;IAED,WAAW,CAAC,GAAoB;QAC9B,IAAI,GAAG,CAAC,KAAK,EAAE;YACb,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,GAAG,EAAE,CAAC;SACjC;IACH,CAAC;IAED,eAAe,CAAC,GAAwB;QACtC,IAAI,GAAG,CAAC,KAAK,EAAE;YACb,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,GAAG,EAAE,CAAC;SACjC;IACH,CAAC;IAED,aAAa,CAAC,GAAsB;QAClC,IAAI,GAAG,CAAC,KAAK,EAAE;YACb,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,GAAG,EAAE,CAAC;SACjC;IACH,CAAC;CACF;AAvDD,sEAuDC;AAED,MAAa,SAAU,SAAQ,uBAAuB;IACpD,YAAmB,WAAmB,EAAE,aAA4B,IAAI;QACtE,KAAK,EAAE,CAAC;QADS,gBAAW,GAAX,WAAW,CAAQ;QAEpC,IAAI,CAAC,UAAU,GAAG,IAAI,mBAAQ,CAAC,WAAW,CAAC,CAAC;QAC5C,IAAI,CAAC,UAAU,GAAG,UAAU,CAAC,CAAC,CAAC,cAAI,CAAC,OAAO,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;IACjE,CAAC;IAED;;OAEG;IACI,KAAK;QACV,IAAI,SAAS,GAAG,IAAI,CAAC,UAAU,EAAE,CAAC;QAClC,IAAI,IAAI,CAAC,MAAM,CAAC,MAAM,GAAG,CAAC,EAAE;YAC1B,MAAM,IAAI,KAAK,CAAC,sCAAsC,CAAC,CAAC;SACzD;QAED,YAAY;QACZ,IAAI,OAAO,GAAG,IAAI,8BAAoB,EAAE,CAAC;QACzC,OAAO,OAAO,CAAC,eAAe,CAAC,SAAS,CAAC,CAAC;IAC5C,CAAC;IAES,UAAU;QAClB,IAAI,mBAAmB,GAAG,IAAI,sBAAsB,CAAC,IAAI,CAAC,CAAC;QAC3D,IAAI,UAAU,GAAG,IAAI,6BAAkB,CACrC,sBAAW,CAAC,UAAU,CAAC,IAAI,CAAC,WAAW,CAAC,CACzC,CAAC;QACF,UAAU,CAAC,oBAAoB,EAAE,CAAC;QAClC,UAAU,CAAC,gBAAgB,CAAC,mBAAmB,CAAC,CAAC;QACjD,IAAI,WAAW,GAAG,IAAI,+BAAmB,CACvC,IAAI,4BAAiB,CAAC,UAAU,CAAC,CAClC,CAAC;QACF,WAAW,CAAC,oBAAoB,EAAE,CAAC;QACnC,WAAW,CAAC,gBAAgB,CAAC,mBAAmB,CAAC,CAAC;QAElD,IAAI,IAAI,GAAG,WAAW,CAAC,UAAU,EAAE,CAAC;QACpC,OAAO,IAAI,CAAC;IACd,CAAC;CACF;AArCD,8BAqCC"}
--------------------------------------------------------------------------------
/dist/util/result.js.map:
--------------------------------------------------------------------------------
1 | {"version":3,"file":"result.js","sourceRoot":"","sources":["../../src/util/result.ts"],"names":[],"mappings":"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"}
--------------------------------------------------------------------------------
/oclif.manifest.json:
--------------------------------------------------------------------------------
1 | {
2 | "version": "0.1.0",
3 | "commands": {
4 | "parse": {
5 | "id": "parse",
6 | "description": "Parse a CWScript source file into AST.",
7 | "strict": true,
8 | "pluginName": "@terran-one/cwsc",
9 | "pluginAlias": "@terran-one/cwsc",
10 | "pluginType": "core",
11 | "aliases": [],
12 | "examples": [
13 | "<%= config.bin %> <%= command.id %> FILE",
14 | "<%= config.bin %> <%= command.id %> FILE --format sexp"
15 | ],
16 | "flags": {
17 | "verbose": {
18 | "name": "verbose",
19 | "type": "boolean",
20 | "char": "V",
21 | "description": "Show verbose output - turns on all logs",
22 | "allowNo": false
23 | },
24 | "silent": {
25 | "name": "silent",
26 | "type": "boolean",
27 | "char": "Q",
28 | "description": "Show no output",
29 | "allowNo": false,
30 | "exclusive": [
31 | "verbose"
32 | ],
33 | "aliases": [
34 | "quiet"
35 | ]
36 | },
37 | "logs": {
38 | "name": "logs",
39 | "type": "option",
40 | "char": "L",
41 | "description": "Show logs of the specified level",
42 | "multiple": true,
43 | "options": [
44 | "none",
45 | "info",
46 | "debug",
47 | "warn",
48 | "error"
49 | ],
50 | "exclusive": [
51 | "silent"
52 | ],
53 | "default": [
54 | "warn",
55 | "error"
56 | ],
57 | "delimiter": ","
58 | },
59 | "log-file": {
60 | "name": "log-file",
61 | "type": "option",
62 | "description": "Write logs to a file",
63 | "multiple": false,
64 | "dependsOn": [
65 | "logs"
66 | ]
67 | },
68 | "project-dir": {
69 | "name": "project-dir",
70 | "type": "option",
71 | "char": "D",
72 | "description": "Specify a directory containing a `cwsproject.toml` file to run the command in a specific project.",
73 | "multiple": false,
74 | "exclusive": [
75 | "project-config",
76 | "project-dir"
77 | ]
78 | },
79 | "cwsconfig": {
80 | "name": "cwsconfig",
81 | "type": "option",
82 | "char": "C",
83 | "description": "Specify a path to `cwsconfig.toml` to use base compiler tool settings.",
84 | "multiple": false
85 | },
86 | "X": {
87 | "name": "X",
88 | "type": "option",
89 | "description": "Set a config value temporarily for this command. This flag can be used multiple times to set multiple values.",
90 | "helpLabel": "-Xkey value",
91 | "multiple": true
92 | },
93 | "format": {
94 | "name": "format",
95 | "type": "option",
96 | "description": "Desired format of the parsed AST output",
97 | "required": true,
98 | "multiple": false,
99 | "options": [
100 | "json",
101 | "sexp"
102 | ],
103 | "default": "json"
104 | },
105 | "out": {
106 | "name": "out",
107 | "type": "option",
108 | "char": "o",
109 | "description": "Output file to write the parsed AST to",
110 | "required": false,
111 | "multiple": false
112 | }
113 | },
114 | "args": {
115 | "file": {
116 | "name": "file",
117 | "description": "File to parse into AST; if not provided, can read from .",
118 | "required": true
119 | }
120 | }
121 | }
122 | }
123 | }
--------------------------------------------------------------------------------
/src/cli/BaseCommand.ts:
--------------------------------------------------------------------------------
1 | import { Command, Flags, Args, Interfaces } from '@oclif/core';
2 | import * as fs from 'fs-extra';
3 | import * as path from 'path';
4 |
5 | export type FlagsT = Interfaces.InferredFlags<
6 | typeof BaseCommand['baseFlags'] & T['flags']
7 | >;
8 | export type ArgsT = Interfaces.InferredArgs<
9 | T['args']
10 | >;
11 |
12 | export class ConfigKV {
13 | constructor(public key: string, public value: string) {}
14 | }
15 |
16 | export abstract class BaseCommand extends Command {
17 | async loadConfig() {
18 | const userConfig = await fs.readJSON(
19 | path.join(this.config.configDir, 'cwsconfig.json')
20 | );
21 |
22 | this.log('User config:');
23 | console.dir(userConfig);
24 | }
25 |
26 | protected flags!: FlagsT;
27 | protected args!: ArgsT;
28 |
29 | public async init(): Promise {
30 | await super.init();
31 | const { args, flags } = await this.parse({
32 | flags: this.ctor.flags,
33 | baseFlags: (super.ctor as typeof BaseCommand).baseFlags,
34 | args: this.ctor.args,
35 | strict: this.ctor.strict,
36 | });
37 | this.flags = flags as FlagsT;
38 | this.args = args as ArgsT;
39 | }
40 |
41 | static baseFlags = {
42 | verbose: Flags.boolean({
43 | char: 'V',
44 | description: 'Show verbose output - turns on all logs and diagnostics.',
45 | default: false,
46 | }),
47 | silent: Flags.boolean({
48 | char: 'Q',
49 | description: 'Show no output',
50 | default: false,
51 | aliases: ['quiet'],
52 | exclusive: ['verbose'],
53 | }),
54 | 'show-hints': Flags.boolean({
55 | description: 'Show CWScript "hint" and "info" diagnostics when parsing.',
56 | default: false,
57 | exclusive: ['silent'],
58 | }),
59 | 'show-warnings': Flags.boolean({
60 | description: 'Show CWScript "warning" diagnostics when parsing.',
61 | default: true,
62 | exclusive: ['silent'],
63 | }),
64 | logs: Flags.string({
65 | description: 'Show compiler tool logs above a certain level',
66 | options: ['NONE', 'INFO', 'DEBUG', 'WARNING', 'ERROR'],
67 | default: ['ERROR'],
68 | exclusive: ['silent'],
69 | }),
70 | 'log-file': Flags.file({
71 | description: 'Write logs to a file',
72 | env: 'CWSC_LOG_FILE',
73 | dependsOn: ['logs'],
74 | }),
75 | 'project-dir': Flags.directory({
76 | char: 'D',
77 | description:
78 | 'Specify a directory containing a `cwsproject.toml` file to run the command in a specific project.',
79 | exclusive: ['project-config', 'project-dir'],
80 | env: 'CWS_PROJECT_DIR',
81 | }),
82 | cwsconfig: Flags.file({
83 | char: 'C',
84 | description:
85 | 'Specify a path to `cwsconfig.toml` to use base compiler tool settings.',
86 | env: 'CWS_CONFIG',
87 | }),
88 | // set: Flags.custom({
89 | // multiple: true,
90 | // description: `Set a config value temporarily for this command. This flag can be used multiple times to set multiple values.`,
91 | // helpLabel: '-Xset=value',
92 | // parse: async (input: string) => {
93 | // const [key, value] = input.split('=');
94 | // return new ConfigKV(key, value);
95 | // },
96 | // })(),
97 | };
98 |
99 | protected async catch(err: Error & { exitCode?: number }): Promise {
100 | // add any custom logic to handle errors from the command
101 | // or simply return the parent class error handling
102 | return super.catch(err);
103 | }
104 |
105 | protected async finally(_: Error | undefined): Promise {
106 | // called after run and catch regardless of whether or not the command errored
107 | return super.finally(_);
108 | }
109 |
110 | abstract run(): Promise;
111 | }
112 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "@terran-one/cwsc",
3 | "version": "0.1.0",
4 | "license": "MIT",
5 | "main": "dist/index.js",
6 | "typings": "dist/index.d.ts",
7 | "type": "commonjs",
8 | "files": [
9 | "bin",
10 | "dist",
11 | "src",
12 | "/oclif.manifest.json"
13 | ],
14 | "engines": {
15 | "node": ">=10"
16 | },
17 | "bin": {
18 | "cwsc": "./bin/run"
19 | },
20 | "scripts": {
21 | "prepack": "bun run build && oclif manifest",
22 | "postpack": "shx rm -f oclif.manifest.json",
23 | "build": "shx rm -rf dist && tsc --module commonjs && webpack --mode production",
24 | "build:types": "tsc --declaration --emitDeclarationOnly",
25 | "format": "prettier --check ./src/**/*.ts",
26 | "format:fix": "prettier --write ./src/**/*.ts",
27 | "lint": "eslint src --ext .js,.ts",
28 | "lint:fix": "eslint src --ext .js,.ts --fix",
29 | "parse": "ts-node src/parser/index.ts",
30 | "viz": "ts-node src/vizserver.ts",
31 | "cli": "./bin/dev",
32 | "size": "size-limit",
33 | "analyze": "size-limit --why",
34 | "gen:tm-grammar": "ts-node ./scripts/gen-tm-grammar.ts",
35 | "antlr-lexer": "antlr4ts ./grammar/CWScriptLexer.g4 -o ./src",
36 | "antlr-parser": "antlr4ts -visitor ./grammar/CWScriptParser.g4 -o ./src -lib ./src/grammar",
37 | "antlr": "bun run antlr-lexer && bun run antlr-parser",
38 | "doc": "typedoc",
39 | "prepublishOnly": "npm run build",
40 | "test": "jest __tests__"
41 | },
42 | "husky": {
43 | "hooks": {
44 | "pre-commit": "tsdx lint"
45 | }
46 | },
47 | "prettier": {
48 | "printWidth": 80,
49 | "semi": true,
50 | "singleQuote": true,
51 | "trailingComma": "es5"
52 | },
53 | "author": "William Chen",
54 | "module": "dist/cwsc.esm.js",
55 | "oclif": {
56 | "bin": "cwsc",
57 | "dirname": "cwsc",
58 | "commands": "./dist/cli/commands",
59 | "plugins": [
60 | "@oclif/plugin-help",
61 | "@oclif/plugin-autocomplete"
62 | ],
63 | "topicSeparator": " ",
64 | "topics": {}
65 | },
66 | "devDependencies": {
67 | "@size-limit/preset-small-lib": "^7.0.8",
68 | "@swc/cli": "^0.1.62",
69 | "@swc/core": "^1.3.55",
70 | "@swc/jest": "^0.2.26",
71 | "@types/chalk": "^2.2.0",
72 | "@types/cytoscape": "^3.19.4",
73 | "@types/cytoscape-dagre": "^2.3.0",
74 | "@types/ejs": "^3.1.0",
75 | "@types/fs-extra": "^11.0.1",
76 | "@types/jest": "^27.5.0",
77 | "@types/lodash": "^4.14.178",
78 | "@types/omelette": "^0.4.2",
79 | "@types/plist": "^3.0.2",
80 | "antlr4ts-cli": "^0.5.0-alpha.4",
81 | "eslint": "^8.12.0",
82 | "husky": "^7.0.4",
83 | "jest": "^29.5.0",
84 | "oclif": "^3",
85 | "path-browserify": "^1.0.1",
86 | "plist": "^3.0.6",
87 | "prettier": "^2.6.1",
88 | "shx": "^0.3.4",
89 | "size-limit": "^7.0.8",
90 | "swc-loader": "^0.2.3",
91 | "terser-webpack-plugin": "4",
92 | "tmlanguage-generator": "^0.4.0",
93 | "ts-loader": "^9.2.8",
94 | "ts-node": "^10.5.0",
95 | "tsconfig-paths-webpack-plugin": "^3.5.2",
96 | "tslib": "^2.3.1",
97 | "typedoc": "^0.22.13",
98 | "typescript": "^4.6.4",
99 | "typescript-call-graph": "^0.0.3",
100 | "webpack": "5.76.0",
101 | "webpack-cli": "^4.9.2"
102 | },
103 | "dependencies": {
104 | "@oclif/core": "^2",
105 | "@oclif/plugin-autocomplete": "^2.1.9",
106 | "@oclif/plugin-help": "^5",
107 | "antlr4ts": "^0.5.0-alpha.4",
108 | "assert": "^2.0.0",
109 | "buffer": "^6.0.3",
110 | "chalk": "4.1.2",
111 | "commander": "^9.0.0",
112 | "ejs": "^3.1.6",
113 | "fs-extra": "^11.1.1",
114 | "immutable": "^4.0.0",
115 | "listr": "^0.14.3",
116 | "lodash": "^4.17.21",
117 | "omelette": "^0.4.17",
118 | "process": "^0.11.10",
119 | "source-map": "^0.7.3",
120 | "stream-browserify": "^3.0.0",
121 | "toml": "^3.0.0",
122 | "ts-results": "^3.3.0",
123 | "vscode-languageserver": "^8.1.0",
124 | "winston": "^3.8.2",
125 | "yaml": "^1.10.2"
126 | }
127 | }
128 |
--------------------------------------------------------------------------------
/dist/util/result.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 | Object.defineProperty(exports, "__esModule", { value: true });
3 | exports.DgnsResult = exports.CWSValidationError = void 0;
4 | const ts_results_1 = require("ts-results");
5 | class CWSValidationError extends Error {
6 | constructor(diagnostics) {
7 | super();
8 | this.diagnostics = diagnostics;
9 | }
10 | }
11 | exports.CWSValidationError = CWSValidationError;
12 | class DgnsResult {
13 | constructor(res, diagnostics) {
14 | this.res = res;
15 | this.diagnostics = diagnostics;
16 | this.flatMap = this.andThen;
17 | }
18 | static Ok(res, diagnostics) {
19 | return new DgnsResult((0, ts_results_1.Ok)(res), diagnostics);
20 | }
21 | static Err(err, diagnostics) {
22 | return new DgnsResult((0, ts_results_1.Err)(err), diagnostics);
23 | }
24 | isOk() {
25 | return this.res.ok;
26 | }
27 | isErr() {
28 | return this.res.err;
29 | }
30 | map(f) {
31 | if (this.isOk()) {
32 | let x = f(this.res.val, this.diagnostics);
33 | let d = x instanceof DgnsResult ? x.diagnostics : [];
34 | return DgnsResult.Ok(x, [...this.diagnostics, ...d]);
35 | }
36 | else {
37 | return DgnsResult.Err(this.res.val, this.diagnostics);
38 | }
39 | }
40 | mapErr(f) {
41 | if (this.isErr()) {
42 | let x = f(this.res.val, this.diagnostics);
43 | let d = x instanceof DgnsResult ? x.diagnostics : [];
44 | return DgnsResult.Err(f(this.res.val, this.diagnostics), [
45 | ...this.diagnostics,
46 | ...d,
47 | ]);
48 | }
49 | else {
50 | return DgnsResult.Ok(this.res.val, this.diagnostics);
51 | }
52 | }
53 | andThen(f) {
54 | if (this.isOk()) {
55 | let x = f(this.res.val, this.diagnostics);
56 | if (x instanceof DgnsResult) {
57 | return new DgnsResult(x.res, [...this.diagnostics, ...x.diagnostics]);
58 | }
59 | }
60 | return DgnsResult.Err(this.res.val, this.diagnostics);
61 | }
62 | unwrap() {
63 | return this.res.unwrap();
64 | }
65 | static all(results) {
66 | let res = [];
67 | let err;
68 | let diagnostics = [];
69 | let hasErr = false;
70 | for (let result of results) {
71 | diagnostics = [...diagnostics, ...result.diagnostics];
72 | if (result.isOk() && !hasErr) {
73 | res.push(result.res.val);
74 | }
75 | else {
76 | if (!hasErr) {
77 | err = result.res.val;
78 | }
79 | hasErr = true;
80 | }
81 | }
82 | if (hasErr) {
83 | return DgnsResult.Err(err, diagnostics);
84 | }
85 | else {
86 | return DgnsResult.Ok(res, diagnostics);
87 | }
88 | }
89 | static allOk(results) {
90 | let res = [];
91 | let diagnostics = [];
92 | for (let result of results) {
93 | res.push(result.res.val);
94 | diagnostics = [...diagnostics, ...result.diagnostics];
95 | }
96 | return DgnsResult.Ok(res, diagnostics);
97 | }
98 | static allErr(results) {
99 | let diagnostics = [];
100 | for (let result of results) {
101 | diagnostics = [...diagnostics, ...result.diagnostics];
102 | }
103 | return DgnsResult.Err(results[0].res.val, diagnostics);
104 | }
105 | catchErr(errC, f) {
106 | if (this.isErr() && this.res.val instanceof errC) {
107 | let x = f(this.res.val, this.diagnostics);
108 | let d = x instanceof DgnsResult ? x.diagnostics : [];
109 | return new DgnsResult(x.res, [...this.diagnostics, ...d]);
110 | }
111 | else {
112 | return new DgnsResult(this.res, this.diagnostics);
113 | }
114 | }
115 | }
116 | exports.DgnsResult = DgnsResult;
117 | //# sourceMappingURL=result.js.map
--------------------------------------------------------------------------------
/dist/util/position.d.ts:
--------------------------------------------------------------------------------
1 | import { ParserRuleContext } from 'antlr4ts';
2 | import { LinesAndColumns } from 'lines-and-columns';
3 | export declare class TextView {
4 | text: string;
5 | lc: LinesAndColumns;
6 | textLines: string[];
7 | constructor(text: string);
8 | /**
9 | * Returns the character at the given line and character.
10 | * If char is undefined, returns the entire line.
11 | * If oneIndexed is true, line and char are 1-indexed.
12 | * @param line
13 | * @param char
14 | * @param oneIndexed
15 | */
16 | at(line: number, char?: number, oneIndexed?: boolean): string;
17 | /**
18 | * Returns the text in the given range.
19 | * If oneIndexed is true, line and char in the Range are 1-indexed.
20 | * @param range
21 | * @param oneIndexed
22 | */
23 | textInRange(range: Range, oneIndexed?: boolean): string | null;
24 | /**
25 | * Returns the lines in the given range.
26 | * If oneIndexed is true, `startLine` and `endLine` are 1-indexed.
27 | * By default, it expects 0-indexed line numbers.
28 | * @param startLine
29 | * @param endLine
30 | * @param oneIndexed
31 | */
32 | lines(startLine: number, endLine: number, oneIndexed?: boolean): string[];
33 | /**
34 | * Returns the lines surrounding the given line.
35 | * If oneIndexed is true, `line` is 1-indexed.
36 | * By default, it expects 0-indexed line numbers.
37 | *
38 | * @param line Line number to get surrounding lines for.
39 | * @param numLines Number of lines to return on either side of the given line.
40 | * @param oneIndexed Whether the given line number is 1-indexed or 0-indexed.
41 | */
42 | surroundingLines(line: number, numLines: number, oneIndexed?: boolean): {
43 | text: string;
44 | line: number;
45 | }[];
46 | /**
47 | * Returns the lines surrounding the given range.
48 | * If oneIndexed is true, `startLine` and `endLine` are 1-indexed.
49 | * By default, it expects 0-indexed line numbers.
50 | * @param range
51 | * @param numLines
52 | * @param oneIndexed
53 | */
54 | surroundingLinesOfRange(range: Range, numLines: number, oneIndexed?: boolean): {
55 | text: string;
56 | line: number;
57 | }[];
58 | /**
59 | * Returns the text surrounding the given line.
60 | * If oneIndexed is true, `line` is 1-indexed.
61 | * By default, it expects 0-indexed line numbers.
62 | * @param line
63 | * @param numLines
64 | * @param oneIndexed
65 | */
66 | surroundingText(line: number, numLines: number, oneIndexed?: boolean): string;
67 | /**
68 | * Returns the line and character for the given index.
69 | * By default, the line and character returned are 0-indexed unless specified
70 | * by the `makeOneIndexed` parameter.
71 | *
72 | * @param ix
73 | * @param makeOneIndexed Whether the returned line and character should be 1-indexed or 0-indexed.
74 | */
75 | lcAtIndex(ix: number, makeOneIndexed?: boolean): [number, number] | null;
76 | /**
77 | * Returns the Range object for the given indices of start and
78 | * end. Note that the end index is inclusive.
79 | *
80 | * @param start The start index
81 | * @param end The end index
82 | * @param makeOneIndexed Whether the returned Range should be 1-indexed or 0-indexed.
83 | * @returns The Range object, or null if the indices are invalid.
84 | */
85 | range(start: number, end: number, makeOneIndexed?: boolean): Range | null;
86 | rangeOfNode(ctx: ParserRuleContext): Range | null;
87 | }
88 | export declare function getIx(ctx: ParserRuleContext): TextIndices;
89 | /**
90 | * Returns the start and end indices of the given node.
91 | */
92 | export interface TextIndices {
93 | start: number;
94 | end: number;
95 | }
96 | /**
97 | * Compatible with LSP's Range object -- 0-indexed.
98 | */
99 | export interface Range {
100 | start: {
101 | line: number;
102 | character: number;
103 | };
104 | end: {
105 | line: number;
106 | character: number;
107 | };
108 | }
109 |
--------------------------------------------------------------------------------
/dist/util/position.js.map:
--------------------------------------------------------------------------------
1 | {"version":3,"file":"position.js","sourceRoot":"","sources":["../../src/util/position.ts"],"names":[],"mappings":"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"}
--------------------------------------------------------------------------------
/src/util/result.ts:
--------------------------------------------------------------------------------
1 | import { Diagnostic } from 'vscode-languageserver';
2 | import {
3 | Result,
4 | Ok,
5 | Err,
6 | Option,
7 | Some,
8 | None,
9 | ResultOkType,
10 | ResultErrType,
11 | } from 'ts-results';
12 |
13 | export type DgnsOk = DgnsResult>;
14 | export type DgnsErr = DgnsResult>;
15 |
16 | export class CWSValidationError extends Error {
17 | constructor(public diagnostics: Diagnostic[]) {
18 | super();
19 | }
20 | }
21 |
22 | export class DgnsResult = Result> {
23 | constructor(public res: R, public diagnostics: Diagnostic[]) {}
24 |
25 | static Ok(res: T, diagnostics: Diagnostic[]): DgnsOk {
26 | return new DgnsResult(Ok(res), diagnostics) as DgnsOk;
27 | }
28 |
29 | static Err(err: E, diagnostics: Diagnostic[]): DgnsErr {
30 | return new DgnsResult(Err(err), diagnostics) as DgnsErr;
31 | }
32 |
33 | isOk(): this is DgnsOk {
34 | return this.res.ok;
35 | }
36 |
37 | isErr(): this is DgnsErr {
38 | return this.res.err;
39 | }
40 |
41 | map(f: (t: T, d: Diagnostic[]) => U): DgnsResult {
42 | if (this.isOk()) {
43 | let x = f(this.res.val, this.diagnostics);
44 | let d = x instanceof DgnsResult ? x.diagnostics : [];
45 | return DgnsResult.Ok(x, [...this.diagnostics, ...d]);
46 | } else {
47 | return DgnsResult.Err(this.res.val as E, this.diagnostics);
48 | }
49 | }
50 |
51 | mapErr(f: (e: E, d: Diagnostic[]) => U): DgnsResult {
52 | if (this.isErr()) {
53 | let x = f(this.res.val, this.diagnostics);
54 | let d = x instanceof DgnsResult ? x.diagnostics : [];
55 | return DgnsResult.Err(f(this.res.val, this.diagnostics), [
56 | ...this.diagnostics,
57 | ...d,
58 | ]);
59 | } else {
60 | return DgnsResult.Ok(this.res.val as T, this.diagnostics);
61 | }
62 | }
63 |
64 | public flatMap = this.andThen;
65 |
66 | andThen(f: (r: T, d: Diagnostic[]) => DgnsResult): DgnsResult {
67 | if (this.isOk()) {
68 | let x = f(this.res.val, this.diagnostics);
69 | if (x instanceof DgnsResult) {
70 | return new DgnsResult(x.res, [...this.diagnostics, ...x.diagnostics]);
71 | }
72 | }
73 | return DgnsResult.Err(this.res.val as E, this.diagnostics);
74 | }
75 |
76 | unwrap(): T {
77 | return this.res.unwrap();
78 | }
79 |
80 | static all(results: DgnsResult[]): DgnsResult {
81 | let res: T[] = [];
82 | let err: E;
83 | let diagnostics: Diagnostic[] = [];
84 | let hasErr = false;
85 | for (let result of results) {
86 | diagnostics = [...diagnostics, ...result.diagnostics];
87 | if (result.isOk() && !hasErr) {
88 | res.push(result.res.val);
89 | } else {
90 | if (!hasErr) {
91 | err = result.res.val as E;
92 | }
93 | hasErr = true;
94 | }
95 | }
96 | if (hasErr) {
97 | return DgnsResult.Err(err!, diagnostics);
98 | } else {
99 | return DgnsResult.Ok(res, diagnostics);
100 | }
101 | }
102 |
103 | static allOk(results: DgnsOk[]): DgnsOk {
104 | let res: T[] = [];
105 | let diagnostics: Diagnostic[] = [];
106 | for (let result of results) {
107 | res.push(result.res.val);
108 | diagnostics = [...diagnostics, ...result.diagnostics];
109 | }
110 | return DgnsResult.Ok(res, diagnostics);
111 | }
112 |
113 | static allErr(results: DgnsErr[]): DgnsErr {
114 | let diagnostics: Diagnostic[] = [];
115 | for (let result of results) {
116 | diagnostics = [...diagnostics, ...result.diagnostics];
117 | }
118 | return DgnsResult.Err(results[0].res.val as E, diagnostics);
119 | }
120 |
121 | catchErr(
122 | errC: new (...args: any[]) => F,
123 | f: (e: F, d: Diagnostic[]) => DgnsResult
124 | ): DgnsResult {
125 | if (this.isErr() && this.res.val instanceof errC) {
126 | let x = f(this.res.val, this.diagnostics);
127 | let d = x instanceof DgnsResult ? x.diagnostics : [];
128 | return new DgnsResult(x.res, [...this.diagnostics, ...d]);
129 | } else {
130 | return new DgnsResult(this.res, this.diagnostics);
131 | }
132 | }
133 | }
134 |
--------------------------------------------------------------------------------
/dist/grammar/CWScriptLexer.d.ts:
--------------------------------------------------------------------------------
1 | import { ATN } from "antlr4ts/atn/ATN";
2 | import { CharStream } from "antlr4ts/CharStream";
3 | import { Lexer } from "antlr4ts/Lexer";
4 | import { Vocabulary } from "antlr4ts/Vocabulary";
5 | export declare class CWScriptLexer extends Lexer {
6 | static readonly DEBUG = 1;
7 | static readonly CONTRACT = 2;
8 | static readonly INTERFACE = 3;
9 | static readonly IMPORT = 4;
10 | static readonly IMPLEMENTS = 5;
11 | static readonly EXTENDS = 6;
12 | static readonly ERROR = 7;
13 | static readonly EVENT = 8;
14 | static readonly DEFER = 9;
15 | static readonly INSTANTIATE_NOW = 10;
16 | static readonly EXEC_NOW = 11;
17 | static readonly QUERY_NOW = 12;
18 | static readonly DELEGATE_EXEC = 13;
19 | static readonly INSTANTIATE = 14;
20 | static readonly EXEC = 15;
21 | static readonly QUERY = 16;
22 | static readonly REPLY = 17;
23 | static readonly FOR = 18;
24 | static readonly IN = 19;
25 | static readonly FROM = 20;
26 | static readonly STATE = 21;
27 | static readonly IF = 22;
28 | static readonly IS = 23;
29 | static readonly TRY = 24;
30 | static readonly CATCH = 25;
31 | static readonly ELSE = 26;
32 | static readonly NOT = 27;
33 | static readonly NONE = 28;
34 | static readonly MUT = 29;
35 | static readonly AND = 30;
36 | static readonly OR = 31;
37 | static readonly TRUE = 32;
38 | static readonly FALSE = 33;
39 | static readonly FN = 34;
40 | static readonly LET = 35;
41 | static readonly CONST = 36;
42 | static readonly FAIL = 37;
43 | static readonly RETURN = 38;
44 | static readonly STRUCT = 39;
45 | static readonly ENUM = 40;
46 | static readonly TYPE = 41;
47 | static readonly EMIT = 42;
48 | static readonly AS = 43;
49 | static readonly TILDE = 44;
50 | static readonly LPAREN = 45;
51 | static readonly RPAREN = 46;
52 | static readonly LBRACK = 47;
53 | static readonly RBRACK = 48;
54 | static readonly LBRACE = 49;
55 | static readonly RBRACE = 50;
56 | static readonly DOT = 51;
57 | static readonly COMMA = 52;
58 | static readonly D_QUEST = 53;
59 | static readonly QUEST = 54;
60 | static readonly BANG = 55;
61 | static readonly SEMI = 56;
62 | static readonly COLON = 57;
63 | static readonly D_COLON = 58;
64 | static readonly HASH = 59;
65 | static readonly AT = 60;
66 | static readonly AMP = 61;
67 | static readonly ARROW = 62;
68 | static readonly FAT_ARROW = 63;
69 | static readonly BAR = 64;
70 | static readonly S_QUOTE = 65;
71 | static readonly D_QUOTE = 66;
72 | static readonly EQ = 67;
73 | static readonly EQ_EQ = 68;
74 | static readonly NEQ = 69;
75 | static readonly PLUS = 70;
76 | static readonly PLUS_EQ = 71;
77 | static readonly MINUS = 72;
78 | static readonly MINUS_EQ = 73;
79 | static readonly MUL = 74;
80 | static readonly MUL_EQ = 75;
81 | static readonly DIV = 76;
82 | static readonly DIV_EQ = 77;
83 | static readonly MOD = 78;
84 | static readonly MOD_EQ = 79;
85 | static readonly LT = 80;
86 | static readonly LT_EQ = 81;
87 | static readonly GT = 82;
88 | static readonly GT_EQ = 83;
89 | static readonly POW = 84;
90 | static readonly Ident = 85;
91 | static readonly StringLiteral = 86;
92 | static readonly IntLiteral = 87;
93 | static readonly DecLiteral = 88;
94 | static readonly BoolLiteral = 89;
95 | static readonly CWSPEC_LINE_COMMENT = 90;
96 | static readonly CWSPEC_BLOCK_COMMENT = 91;
97 | static readonly LINE_COMMENT = 92;
98 | static readonly BLOCK_COMMENT = 93;
99 | static readonly WS = 94;
100 | static readonly channelNames: string[];
101 | static readonly modeNames: string[];
102 | static readonly ruleNames: string[];
103 | private static readonly _LITERAL_NAMES;
104 | private static readonly _SYMBOLIC_NAMES;
105 | static readonly VOCABULARY: Vocabulary;
106 | get vocabulary(): Vocabulary;
107 | constructor(input: CharStream);
108 | get grammarFileName(): string;
109 | get ruleNames(): string[];
110 | get serializedATN(): string;
111 | get channelNames(): string[];
112 | get modeNames(): string[];
113 | private static readonly _serializedATNSegments;
114 | private static readonly _serializedATNSegment0;
115 | private static readonly _serializedATNSegment1;
116 | static readonly _serializedATN: string;
117 | static __ATN: ATN;
118 | static get _ATN(): ATN;
119 | }
120 |
--------------------------------------------------------------------------------
/examples/terraswap/TerraswapFactory.cws:
--------------------------------------------------------------------------------
1 | import * from "./common.cws"
2 |
3 | contract TerraswapFactory {
4 |
5 | error Unauthorized()
6 | event UpdateConfig()
7 |
8 | state {
9 | config: Config // since these are not option, we will type-check these...
10 | tmp_pair_info: TmpPairInfo
11 | pairs[U8]: PairInfo? = None
12 | allow_native_tokens[U8[2]]: U8? = None
13 | }
14 |
15 | fn query_decimals!(account_addr: address, asset_info: AssetInfo) -> U8 {
16 | if asset_info is AssetInfo.#Token {
17 | let { contract_addr } = asset_info
18 | let token_info = query! CW20(asset_info).#token_info()
19 | return token_info.decimals
20 | } else {
21 | // asset_info is AssetInfo::NativeToken
22 | // this does a self-query
23 | let res = query! $.#native_token_decimals(asset_info.denom)
24 | return res.decimals
25 | }
26 | }
27 |
28 | // #1. how do we let users pass context around ($)
29 | // #2. how can we make it obvious that instantiate is not a function that the user can call
30 | #instantiate(pair_code_id: U64, token_code_id: U64) {
31 | $state.config = Config(token_code_id, pair_code_id, $info.sender)
32 | }
33 |
34 | exec #update_config(owner?: String, token_code_id?: U64, pair_code_id?: U64) {
35 | if $info.sender != $state.config.owner {
36 | fail! Unauthorized()
37 | }
38 |
39 | // auto-unwraps if safe
40 | if owner? {
41 | $state.config.owner = Address.validate!(owner)
42 | }
43 |
44 | if token_code_id? {
45 | $state.token_code_id = token_code_id
46 | }
47 |
48 | if pair_code_id? {
49 | $state.pair_code_id = pair_code_id
50 | }
51 |
52 | emit UpdateConfig()
53 | }
54 |
55 | reply.success post_instantiate() {
56 | let { tmp_pair_info } = $state
57 | // parse_response!
58 | // the parse_response!() function expects the context variable "$"
59 | let response = Wasm.Instantiate::parse_response!($data)
60 | let pair_contract = response.address
61 | let pair_info = query! TerraswapPair(pair_contract).#pair() ~ .token_supply
62 | $state.pairs = PairInfo(
63 | Address.Canonical!(pair_info.liquidity_token),
64 | Address.Canonical!(pair_info.liquidity_token),
65 | asset_infos=tmp_pair_info.asset_infos,
66 | asset_decimals=tmp_pair_info.asset_decimals
67 | )
68 | emit PostInstantiate(pair_contract, pair_info.liquidity_token)
69 | }
70 |
71 | exec #create_pair(asset_infos: AssetInfo[2]) {
72 | if asset_infos[0] == asset_infos[1] {
73 | fail! "same asset"
74 | }
75 |
76 | let asset_1_decimal = query_decimals!($env.contract.address, asset_infos[0])
77 | let asset_2_decimal = query_decimals!($env.contract.address, asset_infos[1])
78 | let asset_decimals = [asset_1_decimal, asset_2_decimal]
79 |
80 | let pair_key = String!(asset_infos[0]) + String!(asset_infos[1])
81 |
82 | // $state::pairs::has_key(pair_key)
83 | // optimization: check if key is there
84 | if pair_key in $state.pairs {
85 | fail! "Pair already exists"
86 | }
87 |
88 | $state.tmp_pair_info = TmpPairInfo { pair_key, asset_infos, asset_decimals }
89 | emit CreatePair(asset_infos[0], asset_infos[1])
90 |
91 | @gas_limit(5000000)
92 | @reply.on_success(post_instantiate)
93 | instantiate! #TerraswapPair(asset_infos, $state.config.token_code_id, asset_decimals) {
94 | code_id: $state.config.pair_code_id,
95 | admin: $env.contract.address,
96 | label: "pair"
97 | }
98 | }
99 |
100 | exec #add_native_token_decimals(denom: String, decimals: U8) {
101 | if $info.sender != $state.config.owner {
102 | fail! Unauthorized()
103 | }
104 |
105 | let balance = query! Bank.#balance($env.contract.address, denom)
106 |
107 | if balance.amount == 0 {
108 | fail! "A balance greater than zero is required by the factory for verification"
109 | }
110 |
111 | $state.allow_native_tokens[denom] = decimals
112 | emit AddAllowNativeToken(denom, decimals)
113 | }
114 |
115 | query #config() {
116 | return $state.config
117 | }
118 |
119 | query #pair(asset_infos: AssetInfo[2]) {
120 | let pairs = $state.pairs[asset_infos]
121 | return { pairs } // type is inferred
122 | // intuition is, if you're too lazy to name it and define it,
123 | // it probably can be referred to as just the response type of query
124 | }
125 |
126 | query #native_token_decimal(denom: String) {
127 | let decimals = $state.allow_native_tokens[denom]
128 | return { decimals }
129 | }
130 |
131 | }
132 |
--------------------------------------------------------------------------------
/dist/cli/BaseCommand.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 | var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3 | if (k2 === undefined) k2 = k;
4 | var desc = Object.getOwnPropertyDescriptor(m, k);
5 | if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6 | desc = { enumerable: true, get: function() { return m[k]; } };
7 | }
8 | Object.defineProperty(o, k2, desc);
9 | }) : (function(o, m, k, k2) {
10 | if (k2 === undefined) k2 = k;
11 | o[k2] = m[k];
12 | }));
13 | var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14 | Object.defineProperty(o, "default", { enumerable: true, value: v });
15 | }) : function(o, v) {
16 | o["default"] = v;
17 | });
18 | var __importStar = (this && this.__importStar) || function (mod) {
19 | if (mod && mod.__esModule) return mod;
20 | var result = {};
21 | if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
22 | __setModuleDefault(result, mod);
23 | return result;
24 | };
25 | Object.defineProperty(exports, "__esModule", { value: true });
26 | exports.BaseCommand = exports.ConfigKV = void 0;
27 | const core_1 = require("@oclif/core");
28 | const fs = __importStar(require("fs-extra"));
29 | const path = __importStar(require("path"));
30 | class ConfigKV {
31 | constructor(key, value) {
32 | this.key = key;
33 | this.value = value;
34 | }
35 | }
36 | exports.ConfigKV = ConfigKV;
37 | class BaseCommand extends core_1.Command {
38 | async loadConfig() {
39 | const userConfig = await fs.readJSON(path.join(this.config.configDir, 'cwsconfig.json'));
40 | this.log('User config:');
41 | console.dir(userConfig);
42 | }
43 | async init() {
44 | await super.init();
45 | const { args, flags } = await this.parse({
46 | flags: this.ctor.flags,
47 | baseFlags: super.ctor.baseFlags,
48 | args: this.ctor.args,
49 | strict: this.ctor.strict,
50 | });
51 | this.flags = flags;
52 | this.args = args;
53 | }
54 | async catch(err) {
55 | // add any custom logic to handle errors from the command
56 | // or simply return the parent class error handling
57 | return super.catch(err);
58 | }
59 | async finally(_) {
60 | // called after run and catch regardless of whether or not the command errored
61 | return super.finally(_);
62 | }
63 | }
64 | exports.BaseCommand = BaseCommand;
65 | BaseCommand.baseFlags = {
66 | verbose: core_1.Flags.boolean({
67 | char: 'V',
68 | description: 'Show verbose output - turns on all logs and diagnostics.',
69 | default: false,
70 | }),
71 | silent: core_1.Flags.boolean({
72 | char: 'Q',
73 | description: 'Show no output',
74 | default: false,
75 | aliases: ['quiet'],
76 | exclusive: ['verbose'],
77 | }),
78 | 'show-hints': core_1.Flags.boolean({
79 | description: 'Show CWScript "hint" and "info" diagnostics when parsing.',
80 | default: false,
81 | exclusive: ['silent'],
82 | }),
83 | 'show-warnings': core_1.Flags.boolean({
84 | description: 'Show CWScript "warning" diagnostics when parsing.',
85 | default: true,
86 | exclusive: ['silent'],
87 | }),
88 | logs: core_1.Flags.string({
89 | description: 'Show compiler tool logs above a certain level',
90 | options: ['NONE', 'INFO', 'DEBUG', 'WARNING', 'ERROR'],
91 | default: ['ERROR'],
92 | exclusive: ['silent'],
93 | }),
94 | 'log-file': core_1.Flags.file({
95 | description: 'Write logs to a file',
96 | env: 'CWSC_LOG_FILE',
97 | dependsOn: ['logs'],
98 | }),
99 | 'project-dir': core_1.Flags.directory({
100 | char: 'D',
101 | description: 'Specify a directory containing a `cwsproject.toml` file to run the command in a specific project.',
102 | exclusive: ['project-config', 'project-dir'],
103 | env: 'CWS_PROJECT_DIR',
104 | }),
105 | cwsconfig: core_1.Flags.file({
106 | char: 'C',
107 | description: 'Specify a path to `cwsconfig.toml` to use base compiler tool settings.',
108 | env: 'CWS_CONFIG',
109 | }),
110 | // set: Flags.custom({
111 | // multiple: true,
112 | // description: `Set a config value temporarily for this command. This flag can be used multiple times to set multiple values.`,
113 | // helpLabel: '-Xset=value',
114 | // parse: async (input: string) => {
115 | // const [key, value] = input.split('=');
116 | // return new ConfigKV(key, value);
117 | // },
118 | // })(),
119 | };
120 | //# sourceMappingURL=BaseCommand.js.map
--------------------------------------------------------------------------------
/dist/parser/index.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 | var __importDefault = (this && this.__importDefault) || function (mod) {
3 | return (mod && mod.__esModule) ? mod : { "default": mod };
4 | };
5 | Object.defineProperty(exports, "__esModule", { value: true });
6 | exports.CWSParser = exports.CheckSymbolsDeclaredBeforeUse = exports.CWSSyntaxErrorListener = exports.CWSDiagnosticsCollector = void 0;
7 | // @ts-nocheck
8 | const antlr4ts_1 = require("antlr4ts");
9 | const CWScriptLexer_1 = require("../grammar/CWScriptLexer");
10 | const CWScriptParser_1 = require("../grammar/CWScriptParser");
11 | const visitor_1 = require("./visitor");
12 | const position_1 = require("../util/position");
13 | const vscode_languageserver_1 = require("vscode-languageserver");
14 | const path_1 = __importDefault(require("path"));
15 | class CWSDiagnosticsCollector {
16 | constructor() {
17 | this.diagnostics = [];
18 | }
19 | get errors() {
20 | return this.diagnostics.filter((d) => d.severity === vscode_languageserver_1.DiagnosticSeverity.Error);
21 | }
22 | get warnings() {
23 | return this.diagnostics.filter((d) => d.severity === vscode_languageserver_1.DiagnosticSeverity.Warning);
24 | }
25 | get infos() {
26 | return this.diagnostics.filter((d) => d.severity === vscode_languageserver_1.DiagnosticSeverity.Information);
27 | }
28 | get hints() {
29 | return this.diagnostics.filter((d) => d.severity === vscode_languageserver_1.DiagnosticSeverity.Hint);
30 | }
31 | }
32 | exports.CWSDiagnosticsCollector = CWSDiagnosticsCollector;
33 | class CWSSyntaxErrorListener {
34 | constructor(parser) {
35 | this.parser = parser;
36 | }
37 | syntaxError(recognizer, offendingSymbol, line, charPositionInLine, msg, e) {
38 | this.parser.diagnostics.push({
39 | severity: vscode_languageserver_1.DiagnosticSeverity.Error,
40 | message: 'SyntaxError: ' + msg,
41 | range: {
42 | start: { line: line - 1, character: charPositionInLine },
43 | end: { line: line - 1, character: charPositionInLine + 1 },
44 | },
45 | });
46 | }
47 | }
48 | exports.CWSSyntaxErrorListener = CWSSyntaxErrorListener;
49 | class CheckSymbolsDeclaredBeforeUse {
50 | get scope() {
51 | return this.scopes[this.scopes.length - 1];
52 | }
53 | constructor(parser) {
54 | this.parser = parser;
55 | this.scopes = [{}];
56 | }
57 | enterIdentExpr(ctx) {
58 | if (!this.scope[ctx.ident().text]) {
59 | this.parser.diagnostics.push({
60 | message: `Symbol '${ctx.ident().text}' is not declared`,
61 | range: this.env.sourceText.rangeFromNodeCtx(ctx),
62 | severity: vscode_languageserver_1.DiagnosticSeverity.Error,
63 | });
64 | }
65 | }
66 | // definitions below
67 | enterIdentBinding_(ctx) {
68 | this.scope[ctx._name.text] = '';
69 | }
70 | enterImportItemsStmt(ctx) {
71 | ctx._items.forEach((sym) => {
72 | this.scope[sym.text] = '';
73 | });
74 | }
75 | enterParam(ctx) {
76 | this.scope[ctx._name.text] = '';
77 | }
78 | enterInstantiateDefn(ctx) {
79 | this.scope[ctx._name.text] = '';
80 | }
81 | enterFnDefn(ctx) {
82 | if (ctx._name) {
83 | this.scope[ctx._name.text] = '';
84 | }
85 | }
86 | enterStructDefn(ctx) {
87 | if (ctx._name) {
88 | this.scope[ctx._name.text] = '';
89 | }
90 | }
91 | enterEnumDefn(ctx) {
92 | if (ctx._name) {
93 | this.scope[ctx._name.text] = '';
94 | }
95 | }
96 | }
97 | exports.CheckSymbolsDeclaredBeforeUse = CheckSymbolsDeclaredBeforeUse;
98 | class CWSParser extends CWSDiagnosticsCollector {
99 | constructor(sourceInput, sourceFile = null) {
100 | super();
101 | this.sourceInput = sourceInput;
102 | this.sourceText = new position_1.TextView(sourceInput);
103 | this.sourceFile = sourceFile ? path_1.default.resolve(sourceFile) : null;
104 | }
105 | /**
106 | * This is the public-facing interface for parsing a source file.
107 | */
108 | parse() {
109 | let parseTree = this.antlrParse();
110 | if (this.errors.length > 0) {
111 | throw new Error('Syntax error occurred while parsing.');
112 | }
113 | // build AST
114 | let visitor = new visitor_1.CWSASTBuilderVisitor();
115 | return visitor.visitSourceFile(parseTree);
116 | }
117 | antlrParse() {
118 | let syntaxErrorListener = new CWSSyntaxErrorListener(this);
119 | let antlrLexer = new CWScriptLexer_1.CWScriptLexer(antlr4ts_1.CharStreams.fromString(this.sourceInput));
120 | antlrLexer.removeErrorListeners();
121 | antlrLexer.addErrorListener(syntaxErrorListener);
122 | let antlrParser = new CWScriptParser_1.CWScriptParser(new antlr4ts_1.CommonTokenStream(antlrLexer));
123 | antlrParser.removeErrorListeners();
124 | antlrParser.addErrorListener(syntaxErrorListener);
125 | let tree = antlrParser.sourceFile();
126 | return tree;
127 | }
128 | }
129 | exports.CWSParser = CWSParser;
130 | //# sourceMappingURL=index.js.map
--------------------------------------------------------------------------------
/src/parser/index.ts:
--------------------------------------------------------------------------------
1 | // @ts-nocheck
2 | import { ANTLRErrorListener, CharStreams, CommonTokenStream } from 'antlr4ts';
3 | import { CWScriptLexer as ANTLRCWScriptLexer } from '../grammar/CWScriptLexer';
4 | import {
5 | CWScriptParser as ANTLRCWScriptParser,
6 | SourceFileContext,
7 | } from '../grammar/CWScriptParser';
8 | import { CWSASTBuilderVisitor } from './visitor';
9 | import * as AST from '../ast';
10 | import { TextView } from '../util/position';
11 | import { Diagnostic, DiagnosticSeverity } from 'vscode-languageserver';
12 | import { DgnsOk, DgnsResult, DgnsErr } from '../util/result';
13 | import path from 'path';
14 | import { ParseTreeWalker } from 'antlr4ts/tree/ParseTreeWalker';
15 | import * as P from '../grammar/CWScriptParser';
16 | import { CWScriptParserListener } from '../grammar/CWScriptParserListener';
17 | import { RecognitionException } from 'antlr4ts/RecognitionException';
18 |
19 | export abstract class CWSDiagnosticsCollector {
20 | public diagnostics: Diagnostic[] = [];
21 |
22 | public get errors(): Diagnostic[] {
23 | return this.diagnostics.filter(
24 | (d) => d.severity === DiagnosticSeverity.Error
25 | );
26 | }
27 |
28 | public get warnings(): Diagnostic[] {
29 | return this.diagnostics.filter(
30 | (d) => d.severity === DiagnosticSeverity.Warning
31 | );
32 | }
33 |
34 | public get infos(): Diagnostic[] {
35 | return this.diagnostics.filter(
36 | (d) => d.severity === DiagnosticSeverity.Information
37 | );
38 | }
39 |
40 | public get hints(): Diagnostic[] {
41 | return this.diagnostics.filter(
42 | (d) => d.severity === DiagnosticSeverity.Hint
43 | );
44 | }
45 | }
46 |
47 | export class CWSSyntaxErrorListener implements ANTLRErrorListener {
48 | constructor(public parser: CWSParser) {}
49 |
50 | syntaxError(
51 | recognizer: any,
52 | offendingSymbol: any,
53 | line: number,
54 | charPositionInLine: number,
55 | msg: string,
56 | e: RecognitionException | undefined
57 | ) {
58 | this.parser.diagnostics.push({
59 | severity: DiagnosticSeverity.Error,
60 | message: 'SyntaxError: ' + msg,
61 | range: {
62 | start: { line: line - 1, character: charPositionInLine },
63 | end: { line: line - 1, character: charPositionInLine + 1 },
64 | },
65 | });
66 | }
67 | }
68 |
69 | export class CheckSymbolsDeclaredBeforeUse implements CWScriptParserListener {
70 | public scopes: any = [{}];
71 |
72 | get scope() {
73 | return this.scopes[this.scopes.length - 1];
74 | }
75 |
76 | constructor(public parser: CWSParser) {}
77 |
78 | enterIdentExpr(ctx: P.IdentExprContext) {
79 | if (!this.scope[ctx.ident().text]) {
80 | this.parser.diagnostics.push({
81 | message: `Symbol '${ctx.ident().text}' is not declared`,
82 | range: this.env.sourceText.rangeFromNodeCtx(ctx),
83 | severity: DiagnosticSeverity.Error,
84 | });
85 | }
86 | }
87 |
88 | // definitions below
89 | enterIdentBinding_(ctx: P.IdentBinding_Context) {
90 | this.scope[ctx._name.text] = '';
91 | }
92 |
93 | enterImportItemsStmt(ctx: P.ImportItemsStmtContext) {
94 | ctx._items.forEach((sym) => {
95 | this.scope[sym.text] = '';
96 | });
97 | }
98 |
99 | enterParam(ctx: P.ParamContext) {
100 | this.scope[ctx._name.text] = '';
101 | }
102 |
103 | enterInstantiateDefn(ctx: P.InstantiateDefnContext) {
104 | this.scope[ctx._name.text] = '';
105 | }
106 |
107 | enterFnDefn(ctx: P.FnDefnContext) {
108 | if (ctx._name) {
109 | this.scope[ctx._name.text] = '';
110 | }
111 | }
112 |
113 | enterStructDefn(ctx: P.StructDefnContext) {
114 | if (ctx._name) {
115 | this.scope[ctx._name.text] = '';
116 | }
117 | }
118 |
119 | enterEnumDefn(ctx: P.EnumDefnContext) {
120 | if (ctx._name) {
121 | this.scope[ctx._name.text] = '';
122 | }
123 | }
124 | }
125 |
126 | export class CWSParser extends CWSDiagnosticsCollector {
127 | constructor(public sourceInput: string, sourceFile: string | null = null) {
128 | super();
129 | this.sourceText = new TextView(sourceInput);
130 | this.sourceFile = sourceFile ? path.resolve(sourceFile) : null;
131 | }
132 |
133 | /**
134 | * This is the public-facing interface for parsing a source file.
135 | */
136 | public parse(): AST.SourceFile {
137 | let parseTree = this.antlrParse();
138 | if (this.errors.length > 0) {
139 | throw new Error('Syntax error occurred while parsing.');
140 | }
141 |
142 | // build AST
143 | let visitor = new CWSASTBuilderVisitor();
144 | return visitor.visitSourceFile(parseTree);
145 | }
146 |
147 | protected antlrParse(): SourceFileContext {
148 | let syntaxErrorListener = new CWSSyntaxErrorListener(this);
149 | let antlrLexer = new ANTLRCWScriptLexer(
150 | CharStreams.fromString(this.sourceInput)
151 | );
152 | antlrLexer.removeErrorListeners();
153 | antlrLexer.addErrorListener(syntaxErrorListener);
154 | let antlrParser = new ANTLRCWScriptParser(
155 | new CommonTokenStream(antlrLexer)
156 | );
157 | antlrParser.removeErrorListeners();
158 | antlrParser.addErrorListener(syntaxErrorListener);
159 |
160 | let tree = antlrParser.sourceFile();
161 | return tree;
162 | }
163 | }
164 |
--------------------------------------------------------------------------------
/dist/parser/visitor.d.ts:
--------------------------------------------------------------------------------
1 | import { ParserRuleContext } from 'antlr4ts';
2 | import { AbstractParseTreeVisitor } from 'antlr4ts/tree/AbstractParseTreeVisitor';
3 | import * as P from '../grammar/CWScriptParser';
4 | import { CWScriptParserVisitor as ANTLRCWScriptParserVisitor } from '../grammar/CWScriptParserVisitor';
5 | import * as AST from '../ast';
6 | export declare class CWSASTBuilderVisitor extends AbstractParseTreeVisitor implements ANTLRCWScriptParserVisitor {
7 | visitSourceFile(ctx: P.SourceFileContext): AST.SourceFile;
8 | visitContractDefn(ctx: P.ContractDefnContext): AST.ContractDefn;
9 | visitTypePath(ctx: P.TypePathContext): AST.TypePath;
10 | visitTypeVariant(ctx: P.TypeVariantContext): AST.TypeVariant;
11 | visitTypeLens(ctx: P.TypeLensContext): AST.TypeLens;
12 | visitOptionT(ctx: P.OptionTContext): AST.OptionT;
13 | visitListT(ctx: P.ListTContext): AST.ListT | AST.TupleT;
14 | visitTupleT(ctx: P.TupleTContext): AST.TupleT;
15 | visitStructDefn(ctx: P.StructDefnContext): AST.StructDefn;
16 | visitTypeAliasDefn(ctx: P.TypeAliasDefnContext): AST.TypeAliasDefn;
17 | visitInterfaceDefn(ctx: P.InterfaceDefnContext): AST.InterfaceDefn;
18 | visitImportAllStmt(ctx: P.ImportAllStmtContext): AST.ImportAllStmt;
19 | visitImportItemsStmt(ctx: P.ImportItemsStmtContext): AST.ImportItemsStmt;
20 | visitParam(ctx: P.ParamContext): AST.Param;
21 | visitStringLit(ctx: P.StringLitContext): AST.StringLit;
22 | visitContractBlock(ctx: P.ContractBlockContext): AST.ContractBlock;
23 | visitStateDefnBlock(ctx: P.StateDefnBlockContext): AST.StateDefnBlock;
24 | visitStateDefn_Item(ctx: P.StateDefn_ItemContext): AST.StateDefnItem;
25 | visitStateDefn_Map(ctx: P.StateDefn_MapContext): AST.StateDefnMap;
26 | visitFnDefn(ctx: P.FnDefnContext): AST.FnDefn;
27 | visitFnParams(ctx: P.FnParamsContext): AST.List;
28 | visitMapKeyDefn(ctx: P.MapKeyDefnContext): AST.MapKeyDefn;
29 | visitInstantiateDefn(ctx: P.InstantiateDefnContext): AST.InstantiateDefn;
30 | visitInstantiateDecl(ctx: P.InstantiateDeclContext): AST.InstantiateDecl;
31 | visitExecDefn(ctx: P.ExecDefnContext): AST.ExecDefn;
32 | visitExecDecl(ctx: P.ExecDeclContext): AST.ExecDecl;
33 | visitQueryDefn(ctx: P.QueryDefnContext): AST.QueryDefn;
34 | visitQueryDecl(ctx: P.QueryDeclContext): AST.QueryDecl;
35 | visitErrorDefn(ctx: P.ErrorDefnContext): AST.ErrorDefn;
36 | visitStructDefn_fn(ctx: P.StructDefn_fnContext): AST.StructDefn;
37 | visitErrorDefnBlock(ctx: P.ErrorDefnBlockContext): AST.ErrorDefnBlock;
38 | visitEventDefn(ctx: P.EventDefnContext): AST.EventDefn;
39 | visitEventDefnBlock(ctx: P.EventDefnBlockContext): AST.EventDefnBlock;
40 | visitReplyDefn(ctx: P.ReplyDefnContext): AST.ReplyDefn;
41 | visitEnumDefn(ctx: P.EnumDefnContext): AST.EnumDefn;
42 | visitVariant_struct(ctx: P.Variant_structContext): AST.EnumVariantStruct;
43 | visitParamList(ctx: P.ParamListContext): AST.List;
44 | visitVariant_unit(ctx: P.Variant_unitContext): AST.EnumVariantUnit;
45 | visitDebugStmt_(ctx: P.DebugStmt_Context): AST.DebugStmt;
46 | visitDebugStmt(ctx: P.DebugStmtContext): AST.DebugStmt;
47 | visitLetStmt_(ctx: P.LetStmt_Context): AST.LetStmt;
48 | visitLetStmt(ctx: P.LetStmtContext): AST.LetStmt;
49 | visitConstStmt_(ctx: P.ConstStmt_Context): AST.ConstStmt;
50 | visitConstStmt(ctx: P.ConstStmtContext): AST.ConstStmt;
51 | visitAssignStmt_(ctx: P.AssignStmt_Context): AST.AssignStmt;
52 | visitAssignStmt(ctx: P.AssignStmtContext): AST.AssignStmt;
53 | visitIfStmt_(ctx: P.IfStmt_Context): AST.IfStmt;
54 | visitElseClause(ctx: P.ElseClauseContext): AST.Block;
55 | visitBlock(ctx: P.BlockContext): AST.Block;
56 | visitForStmt_(ctx: P.ForStmt_Context): AST.ForStmt;
57 | visitForStmt(ctx: P.ForStmtContext): AST.ForStmt;
58 | visitExecStmt(ctx: P.ExecStmtContext): AST.ExecStmt;
59 | visitDelegateExecStmt(ctx: P.DelegateExecStmtContext): AST.DelegateExecStmt;
60 | visitInstantiateStmt(ctx: P.InstantiateStmtContext): AST.InstantiateStmt;
61 | visitCallOptions(ctx: P.CallOptionsContext): AST.List;
62 | visitEmitStmt(ctx: P.EmitStmtContext): AST.EmitStmt;
63 | visitReturnStmt(ctx: P.ReturnStmtContext): AST.ReturnStmt;
64 | visitFailStmt(ctx: P.FailStmtContext): AST.FailStmt;
65 | visitExprStmt(ctx: P.ExprStmtContext): AST.Expr;
66 | visitIdentBinding_(ctx: P.IdentBinding_Context): AST.IdentBinding;
67 | visitStructBinding(ctx: P.StructBindingContext): AST.StructBinding;
68 | visitTupleBinding(ctx: P.TupleBindingContext): AST.TupleBinding;
69 | visitIdentLHS(ctx: P.IdentLHSContext): AST.IdentLHS;
70 | visitDotLHS(ctx: P.DotLHSContext): AST.DotLHS;
71 | visitIndexLHS(ctx: P.IndexLHSContext): AST.IndexLHS;
72 | visitGroupedExpr(ctx: P.GroupedExprContext): AST.GroupedExpr;
73 | visitGrouped2Expr(ctx: P.Grouped2ExprContext): AST.Grouped2Expr;
74 | visitDotExpr(ctx: P.DotExprContext): AST.DotExpr;
75 | visitAsExpr(ctx: P.AsExprContext): AST.AsExpr;
76 | visitIndexExpr(ctx: P.IndexExprContext): AST.IndexExpr;
77 | visitDColonExpr(ctx: P.DColonExprContext): AST.DColonExpr;
78 | visitTypeDColonExpr(ctx: P.TypeDColonExprContext): AST.DColonExpr;
79 | visitArg(ctx: P.ArgContext): AST.Arg;
80 | visitFnCallExpr(ctx: P.FnCallExprContext): AST.FnCallExpr;
81 | visitTypeFnCallExpr(ctx: P.TypeFnCallExprContext): AST.FnCallExpr;
82 | visitMulExpr(ctx: P.MulExprContext): AST.BinOpExpr;
83 | visitAddExpr(ctx: P.AddExprContext): AST.BinOpExpr;
84 | visitCompExpr(ctx: P.CompExprContext): AST.BinOpExpr;
85 | visitEqExpr(ctx: P.EqExprContext): AST.BinOpExpr;
86 | visitNoneCheckExpr(ctx: P.NoneCheckExprContext): AST.NoneCheckExpr;
87 | visitIsExpr(ctx: P.IsExprContext): AST.IsExpr;
88 | visitInExpr(ctx: P.InExprContext): AST.InExpr;
89 | visitShortTryExpr(ctx: P.ShortTryExprContext): AST.TryCatchElseExpr;
90 | visitTryCatchElseExpr_(ctx: P.TryCatchElseExpr_Context): AST.TryCatchElseExpr;
91 | visitCatch(ctx: P.CatchContext): AST.CatchClause;
92 | visitCatchBind(ctx: P.CatchBindContext): AST.CatchClause;
93 | visitAndExpr(ctx: P.AndExprContext): AST.AndExpr;
94 | visitOrExpr(ctx: P.OrExprContext): AST.OrExpr;
95 | visitQueryNowExpr(ctx: P.QueryNowExprContext): AST.QueryNowExpr;
96 | visitFailExpr(ctx: P.FailExprContext): AST.FailExpr;
97 | visitClosure(ctx: P.ClosureContext): AST.Closure;
98 | visitTupleExpr(ctx: P.TupleExprContext): AST.TupleExpr;
99 | visitClosureParams(ctx: P.ClosureParamsContext): AST.List;
100 | visitMemberVal(ctx: P.MemberValContext): AST.MemberVal;
101 | visitStructExpr(ctx: P.StructExprContext): AST.StructExpr;
102 | visitUnitVariantExpr(ctx: P.UnitVariantExprContext): AST.UnitVariantExpr;
103 | visitIntLit(ctx: P.IntLitContext): AST.IntLit;
104 | visitDecLit(ctx: P.DecLitContext): AST.DecLit;
105 | visitBoolLit(ctx: P.BoolLitContext): AST.BoolLit;
106 | visitNoneLit(ctx: P.NoneLitContext): AST.NoneLit;
107 | visitIdent(ctx: P.IdentContext): AST.Ident;
108 | protected vlist(ctx: ParserRuleContext[]): AST.List;
109 | protected defaultResult(): AST.AST;
110 | }
111 |
--------------------------------------------------------------------------------
/scripts/generate-textmate.ts:
--------------------------------------------------------------------------------
1 | import * as tm from 'tmlanguage-generator';
2 | import path from 'path';
3 | import plist from 'plist';
4 |
5 | export const grammarPath = path.resolve(__dirname, '../cwscript.tmlanguage');
6 |
7 | type Rule = tm.Rule;
8 | type IncludeRule = tm.IncludeRule;
9 | type BeginEndRule = tm.BeginEndRule;
10 | type MatchRule = tm.MatchRule;
11 | type Grammar = tm.Grammar;
12 |
13 | export type CWScriptScope =
14 | | 'comment.block.cwscript'
15 | | 'comment.line.double-slash.cwscript'
16 | | 'constant.character.escape.cwscript'
17 | | 'constant.numeric.cwscript'
18 | | 'constant.language.cwscript'
19 | | 'entity.name.function.cwscript'
20 | | 'keyword.control.declaration.cwscript'
21 | | 'string.quoted.single.cwscript'
22 | | 'string.quoted.multi.cwscript'
23 | | 'variable.other.readwrite.cwscript'
24 | | 'variable.other.property.cwscript'
25 | | 'punctuation.definition.template-expression.begin.cwscript'
26 | | 'punctuation.definition.template-expression.end.cwscript';
27 |
28 | const bounded = (text: string) => `\\b${text}\\b`;
29 | // eslint-disable-next-line @typescript-eslint/no-unused-vars
30 | const after = (regex: string) => `(?<=${regex})`;
31 | const notAfter = (regex: string) => `(? `(?=${regex})`;
33 | const notBefore = (regex: string) => `(?!${regex})`;
34 |
35 | const meta: typeof tm.meta = tm.meta;
36 | const identifierStart = '[_$[:alpha:]]';
37 | const identifierContinue = '[_$[:alnum:]]';
38 | const identifier = bounded(`${identifierStart}${identifierContinue}*`);
39 | const directive = bounded(`[_a-zA-Z-0-9]+`);
40 |
41 | // whitespace. ideally we'd tokenize in-line block comments, but that's a lot of work. For now, ignore them.
42 | const ws = `(?:[ \\t\\r\\n]|\\/\\*(?:\\*(?!\\/)|[^*])*\\*\\/)*`;
43 |
44 | const keywords = [
45 | 'metadata',
46 | 'targetScope',
47 | 'resource',
48 | 'module',
49 | 'param',
50 | 'var',
51 | 'output',
52 | 'for',
53 | 'in',
54 | 'if',
55 | 'existing',
56 | 'import',
57 | 'as',
58 | 'type',
59 | 'with',
60 | 'using',
61 | ];
62 |
63 | const keywordExpression: MatchRule = {
64 | key: 'keyword',
65 | scope: 'keyword.control.declaration.cwscript',
66 | match: bounded(`(${keywords.join('|')})`),
67 | };
68 |
69 | const lineComment: MatchRule = {
70 | key: 'line-comment',
71 | scope: 'comment.line.double-slash.cwscript',
72 | match: `//.*${before(`$`)}`,
73 | };
74 |
75 | const blockComment: BeginEndRule = {
76 | key: 'block-comment',
77 | scope: 'comment.block.cwscript',
78 | begin: `/\\*`,
79 | end: `\\*/`,
80 | };
81 |
82 | const comments: IncludeRule = {
83 | key: 'comments',
84 | patterns: [lineComment, blockComment],
85 | };
86 |
87 | function withComments(input: Rule[]): Rule[] {
88 | return [...input, comments];
89 | }
90 |
91 | const expression: IncludeRule = {
92 | key: 'expression',
93 | patterns: [
94 | /* placeholder filled later due to cycle*/
95 | ],
96 | };
97 |
98 | const escapeChar: MatchRule = {
99 | key: 'escape-character',
100 | scope: 'constant.character.escape.cwscript',
101 | match: `\\\\(u{[0-9A-Fa-f]+}|n|r|t|\\\\|'|\\\${)`,
102 | };
103 |
104 | const stringVerbatim: BeginEndRule = {
105 | key: 'string-verbatim',
106 | scope: 'string.quoted.multi.cwscript',
107 | begin: `'''`,
108 | end: `'''`,
109 | patterns: [],
110 | };
111 |
112 | const stringSubstitution: BeginEndRule = {
113 | key: 'string-literal-subst',
114 | scope: meta,
115 | begin: `${notAfter(`\\\\`)}(\\\${)`,
116 | beginCaptures: {
117 | '1': { scope: 'punctuation.definition.template-expression.begin.cwscript' },
118 | },
119 | end: `(})`,
120 | endCaptures: {
121 | '1': { scope: 'punctuation.definition.template-expression.end.cwscript' },
122 | },
123 | patterns: withComments([expression]),
124 | };
125 |
126 | const stringLiteral: BeginEndRule = {
127 | key: 'string-literal',
128 | scope: 'string.quoted.single.cwscript',
129 | begin: `'${notBefore(`''`)}`,
130 | end: `'`,
131 | patterns: [escapeChar, stringSubstitution],
132 | };
133 |
134 | const numericLiteral: MatchRule = {
135 | key: 'numeric-literal',
136 | scope: 'constant.numeric.cwscript',
137 | match: `[0-9]+`,
138 | };
139 |
140 | const namedLiteral: MatchRule = {
141 | key: 'named-literal',
142 | scope: 'constant.language.cwscript',
143 | match: bounded(`(true|false|null)`),
144 | };
145 |
146 | const identifierExpression: MatchRule = {
147 | key: 'identifier',
148 | scope: 'variable.other.readwrite.cwscript',
149 | match: `${identifier}${notBefore(`${ws}\\(`)}`,
150 | };
151 |
152 | const objectLiteral: BeginEndRule = {
153 | key: 'object-literal',
154 | scope: meta,
155 | begin: `{`,
156 | end: `}`,
157 | patterns: withComments([
158 | {
159 | key: 'object-property-key',
160 | scope: 'variable.other.property.cwscript',
161 | match: `${identifier}${before(`${ws}:`)}`,
162 | },
163 | expression,
164 | ]),
165 | };
166 |
167 | const arrayLiteral: BeginEndRule = {
168 | key: 'array-literal',
169 | scope: meta,
170 | begin: `\\[${notBefore(`${ws}${bounded(`for`)}`)}`,
171 | end: `]`,
172 | patterns: withComments([expression]),
173 | };
174 |
175 | const functionCall: BeginEndRule = {
176 | key: 'function-call',
177 | scope: meta,
178 | begin: `(${identifier})${ws}\\(`,
179 | beginCaptures: {
180 | '1': { scope: 'entity.name.function.cwscript' },
181 | },
182 | end: `\\)`,
183 | patterns: withComments([expression]),
184 | };
185 |
186 | const decorator: BeginEndRule = {
187 | key: 'decorator',
188 | scope: meta,
189 | begin: `@${ws}${before(identifier)}`,
190 | end: ``,
191 | patterns: withComments([expression]),
192 | };
193 |
194 | const lambdaStart =
195 | `(` +
196 | `\\(${ws}${identifier}${ws}(,${ws}${identifier}${ws})*\\)|` +
197 | `\\(${ws}\\)|` +
198 | `${ws}${identifier}${ws}` +
199 | `)${before(`${ws}=>`)}`;
200 |
201 | const lambda: BeginEndRule = {
202 | key: 'lambda-start',
203 | scope: meta,
204 | begin: lambdaStart,
205 | beginCaptures: {
206 | '1': {
207 | scope: meta,
208 | patterns: withComments([identifierExpression]),
209 | },
210 | },
211 | end: `${ws}=>`,
212 | };
213 |
214 | const directiveStatement: BeginEndRule = {
215 | key: 'directive',
216 | scope: meta,
217 | begin: `#${directive}`,
218 | end: `$`,
219 | patterns: withComments([
220 | {
221 | key: 'directive-variable',
222 | scope: 'keyword.control.declaration.cwscript',
223 | match: directive,
224 | },
225 | ]),
226 | };
227 |
228 | expression.patterns = [
229 | stringLiteral,
230 | stringVerbatim,
231 | numericLiteral,
232 | namedLiteral,
233 | objectLiteral,
234 | arrayLiteral,
235 | keywordExpression,
236 | identifierExpression,
237 | functionCall,
238 | decorator,
239 | lambda,
240 | directiveStatement,
241 | ];
242 |
243 | const grammar: Grammar = {
244 | $schema: tm.schema,
245 | name: 'Bicep',
246 | scopeName: 'source.cwscript',
247 | fileTypes: ['.cwscript'],
248 | patterns: withComments([expression]),
249 | };
250 |
251 | export async function generateGrammar(): Promise {
252 | const json = await tm.emitJSON(grammar);
253 |
254 | return plist.build(JSON.parse(json));
255 | }
256 |
--------------------------------------------------------------------------------
/dist/util/position.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 | Object.defineProperty(exports, "__esModule", { value: true });
3 | exports.getIx = exports.TextView = void 0;
4 | const lines_and_columns_1 = require("lines-and-columns");
5 | class TextView {
6 | constructor(text) {
7 | this.text = text;
8 | this.lc = new lines_and_columns_1.LinesAndColumns(text);
9 | this.textLines = this.text.split('\n');
10 | }
11 | /**
12 | * Returns the character at the given line and character.
13 | * If char is undefined, returns the entire line.
14 | * If oneIndexed is true, line and char are 1-indexed.
15 | * @param line
16 | * @param char
17 | * @param oneIndexed
18 | */
19 | at(line, char, oneIndexed = false) {
20 | if (oneIndexed) {
21 | line--;
22 | if (char !== undefined) {
23 | char--;
24 | }
25 | }
26 | if (char === undefined) {
27 | return this.textLines[line];
28 | }
29 | else {
30 | return this.textLines[line][char];
31 | }
32 | }
33 | /**
34 | * Returns the text in the given range.
35 | * If oneIndexed is true, line and char in the Range are 1-indexed.
36 | * @param range
37 | * @param oneIndexed
38 | */
39 | textInRange(range, oneIndexed = false) {
40 | // the LineAndColumns library expects a 0-indexed { line, column } object
41 | if (oneIndexed) {
42 | range = {
43 | start: {
44 | line: range.start.line - 1,
45 | character: range.start.character - 1,
46 | },
47 | end: {
48 | line: range.end.line - 1,
49 | character: range.end.character - 1,
50 | },
51 | };
52 | }
53 | let startLineCol = {
54 | line: range.start.line,
55 | column: range.start.character,
56 | };
57 | let endLineCol = {
58 | line: range.end.line,
59 | column: range.end.character,
60 | };
61 | let start = this.lc.indexForLocation(startLineCol);
62 | let end = this.lc.indexForLocation(endLineCol);
63 | if (start === null || end === null) {
64 | return null;
65 | }
66 | return this.text.slice(start, end + 1);
67 | }
68 | /**
69 | * Returns the lines in the given range.
70 | * If oneIndexed is true, `startLine` and `endLine` are 1-indexed.
71 | * By default, it expects 0-indexed line numbers.
72 | * @param startLine
73 | * @param endLine
74 | * @param oneIndexed
75 | */
76 | lines(startLine, endLine, oneIndexed = false) {
77 | if (oneIndexed) {
78 | startLine -= 1;
79 | endLine -= 1;
80 | }
81 | return this.textLines.slice(startLine, endLine + 1);
82 | }
83 | /**
84 | * Returns the lines surrounding the given line.
85 | * If oneIndexed is true, `line` is 1-indexed.
86 | * By default, it expects 0-indexed line numbers.
87 | *
88 | * @param line Line number to get surrounding lines for.
89 | * @param numLines Number of lines to return on either side of the given line.
90 | * @param oneIndexed Whether the given line number is 1-indexed or 0-indexed.
91 | */
92 | surroundingLines(line, numLines, oneIndexed = false) {
93 | if (oneIndexed) {
94 | line -= 1;
95 | }
96 | let start = Math.max(0, line - numLines);
97 | let end = Math.min(this.textLines.length - 1, line + numLines);
98 | return this.lines(start, end).map((x) => ({
99 | text: x,
100 | line: start++ + (oneIndexed ? 1 : 0),
101 | }));
102 | }
103 | /**
104 | * Returns the lines surrounding the given range.
105 | * If oneIndexed is true, `startLine` and `endLine` are 1-indexed.
106 | * By default, it expects 0-indexed line numbers.
107 | * @param range
108 | * @param numLines
109 | * @param oneIndexed
110 | */
111 | surroundingLinesOfRange(range, numLines, oneIndexed = false) {
112 | if (oneIndexed) {
113 | range = {
114 | start: {
115 | line: range.start.line - 1,
116 | character: range.start.character - 1,
117 | },
118 | end: {
119 | line: range.end.line - 1,
120 | character: range.end.character - 1,
121 | },
122 | };
123 | }
124 | let start = Math.max(0, range.start.line - numLines);
125 | let end = Math.min(this.textLines.length - 1, range.end.line + numLines);
126 | return this.lines(start, end).map((x) => ({
127 | text: x,
128 | line: start++ + (oneIndexed ? 1 : 0),
129 | }));
130 | }
131 | /**
132 | * Returns the text surrounding the given line.
133 | * If oneIndexed is true, `line` is 1-indexed.
134 | * By default, it expects 0-indexed line numbers.
135 | * @param line
136 | * @param numLines
137 | * @param oneIndexed
138 | */
139 | surroundingText(line, numLines, oneIndexed = false) {
140 | return this.surroundingLines(line, numLines, oneIndexed).join('\n');
141 | }
142 | /**
143 | * Returns the line and character for the given index.
144 | * By default, the line and character returned are 0-indexed unless specified
145 | * by the `makeOneIndexed` parameter.
146 | *
147 | * @param ix
148 | * @param makeOneIndexed Whether the returned line and character should be 1-indexed or 0-indexed.
149 | */
150 | lcAtIndex(ix, makeOneIndexed = false) {
151 | let loc = this.lc.locationForIndex(ix);
152 | if (loc === null) {
153 | return null;
154 | }
155 | if (makeOneIndexed) {
156 | loc.line += 1;
157 | loc.column += 1;
158 | }
159 | return [loc.line, loc.column];
160 | }
161 | /**
162 | * Returns the Range object for the given indices of start and
163 | * end. Note that the end index is inclusive.
164 | *
165 | * @param start The start index
166 | * @param end The end index
167 | * @param makeOneIndexed Whether the returned Range should be 1-indexed or 0-indexed.
168 | * @returns The Range object, or null if the indices are invalid.
169 | */
170 | range(start, end, makeOneIndexed = false) {
171 | let lcStart = this.lcAtIndex(start, makeOneIndexed);
172 | let lcEnd = this.lcAtIndex(end, makeOneIndexed);
173 | if (lcStart === null || lcEnd === null) {
174 | return null;
175 | }
176 | return {
177 | start: {
178 | line: lcStart[0],
179 | character: lcStart[1],
180 | },
181 | end: {
182 | line: lcEnd[0],
183 | character: lcEnd[1],
184 | },
185 | };
186 | }
187 | rangeOfNode(ctx) {
188 | let pos = getIx(ctx);
189 | return this.range(pos.start, pos.end);
190 | }
191 | }
192 | exports.TextView = TextView;
193 | function getIx(ctx) {
194 | var _a;
195 | let start = ctx.start.startIndex;
196 | let end = ((_a = ctx.stop) === null || _a === void 0 ? void 0 : _a.stopIndex) || ctx.start.stopIndex;
197 | let length = end - start + 1;
198 | return {
199 | start,
200 | end: start + length,
201 | };
202 | }
203 | exports.getIx = getIx;
204 | //# sourceMappingURL=position.js.map
--------------------------------------------------------------------------------
/src/util/position.ts:
--------------------------------------------------------------------------------
1 | import { ParserRuleContext } from 'antlr4ts';
2 | import { TerminalNode } from 'antlr4ts/tree/TerminalNode';
3 | import { LinesAndColumns } from 'lines-and-columns';
4 |
5 | export class TextView {
6 | lc: LinesAndColumns;
7 | textLines: string[];
8 |
9 | constructor(public text: string) {
10 | this.lc = new LinesAndColumns(text);
11 | this.textLines = this.text.split('\n');
12 | }
13 |
14 | /**
15 | * Returns the character at the given line and character.
16 | * If char is undefined, returns the entire line.
17 | * If oneIndexed is true, line and char are 1-indexed.
18 | * @param line
19 | * @param char
20 | * @param oneIndexed
21 | */
22 | public at(line: number, char?: number, oneIndexed: boolean = false): string {
23 | if (oneIndexed) {
24 | line--;
25 | if (char !== undefined) {
26 | char--;
27 | }
28 | }
29 | if (char === undefined) {
30 | return this.textLines[line];
31 | } else {
32 | return this.textLines[line][char];
33 | }
34 | }
35 |
36 | /**
37 | * Returns the text in the given range.
38 | * If oneIndexed is true, line and char in the Range are 1-indexed.
39 | * @param range
40 | * @param oneIndexed
41 | */
42 | public textInRange(range: Range, oneIndexed: boolean = false): string | null {
43 | // the LineAndColumns library expects a 0-indexed { line, column } object
44 | if (oneIndexed) {
45 | range = {
46 | start: {
47 | line: range.start.line - 1,
48 | character: range.start.character - 1,
49 | },
50 | end: {
51 | line: range.end.line - 1,
52 | character: range.end.character - 1,
53 | },
54 | };
55 | }
56 | let startLineCol = {
57 | line: range.start.line,
58 | column: range.start.character,
59 | };
60 | let endLineCol = {
61 | line: range.end.line,
62 | column: range.end.character,
63 | };
64 | let start = this.lc.indexForLocation(startLineCol);
65 | let end = this.lc.indexForLocation(endLineCol);
66 |
67 | if (start === null || end === null) {
68 | return null;
69 | }
70 | return this.text.slice(start, end + 1);
71 | }
72 |
73 | /**
74 | * Returns the lines in the given range.
75 | * If oneIndexed is true, `startLine` and `endLine` are 1-indexed.
76 | * By default, it expects 0-indexed line numbers.
77 | * @param startLine
78 | * @param endLine
79 | * @param oneIndexed
80 | */
81 | public lines(
82 | startLine: number,
83 | endLine: number,
84 | oneIndexed: boolean = false
85 | ): string[] {
86 | if (oneIndexed) {
87 | startLine -= 1;
88 | endLine -= 1;
89 | }
90 | return this.textLines.slice(startLine, endLine + 1);
91 | }
92 |
93 | /**
94 | * Returns the lines surrounding the given line.
95 | * If oneIndexed is true, `line` is 1-indexed.
96 | * By default, it expects 0-indexed line numbers.
97 | *
98 | * @param line Line number to get surrounding lines for.
99 | * @param numLines Number of lines to return on either side of the given line.
100 | * @param oneIndexed Whether the given line number is 1-indexed or 0-indexed.
101 | */
102 | public surroundingLines(
103 | line: number,
104 | numLines: number,
105 | oneIndexed: boolean = false
106 | ) {
107 | if (oneIndexed) {
108 | line -= 1;
109 | }
110 | let start = Math.max(0, line - numLines);
111 | let end = Math.min(this.textLines.length - 1, line + numLines);
112 | return this.lines(start, end).map((x) => ({
113 | text: x,
114 | line: start++ + (oneIndexed ? 1 : 0),
115 | }));
116 | }
117 |
118 | /**
119 | * Returns the lines surrounding the given range.
120 | * If oneIndexed is true, `startLine` and `endLine` are 1-indexed.
121 | * By default, it expects 0-indexed line numbers.
122 | * @param range
123 | * @param numLines
124 | * @param oneIndexed
125 | */
126 | public surroundingLinesOfRange(
127 | range: Range,
128 | numLines: number,
129 | oneIndexed: boolean = false
130 | ) {
131 | if (oneIndexed) {
132 | range = {
133 | start: {
134 | line: range.start.line - 1,
135 | character: range.start.character - 1,
136 | },
137 | end: {
138 | line: range.end.line - 1,
139 | character: range.end.character - 1,
140 | },
141 | };
142 | }
143 | let start = Math.max(0, range.start.line - numLines);
144 | let end = Math.min(this.textLines.length - 1, range.end.line + numLines);
145 | return this.lines(start, end).map((x) => ({
146 | text: x,
147 | line: start++ + (oneIndexed ? 1 : 0),
148 | }));
149 | }
150 |
151 | /**
152 | * Returns the text surrounding the given line.
153 | * If oneIndexed is true, `line` is 1-indexed.
154 | * By default, it expects 0-indexed line numbers.
155 | * @param line
156 | * @param numLines
157 | * @param oneIndexed
158 | */
159 | public surroundingText(
160 | line: number,
161 | numLines: number,
162 | oneIndexed: boolean = false
163 | ): string {
164 | return this.surroundingLines(line, numLines, oneIndexed).join('\n');
165 | }
166 |
167 | /**
168 | * Returns the line and character for the given index.
169 | * By default, the line and character returned are 0-indexed unless specified
170 | * by the `makeOneIndexed` parameter.
171 | *
172 | * @param ix
173 | * @param makeOneIndexed Whether the returned line and character should be 1-indexed or 0-indexed.
174 | */
175 | public lcAtIndex(
176 | ix: number,
177 | makeOneIndexed: boolean = false
178 | ): [number, number] | null {
179 | let loc = this.lc.locationForIndex(ix);
180 | if (loc === null) {
181 | return null;
182 | }
183 | if (makeOneIndexed) {
184 | loc.line += 1;
185 | loc.column += 1;
186 | }
187 | return [loc.line, loc.column];
188 | }
189 |
190 | /**
191 | * Returns the Range object for the given indices of start and
192 | * end. Note that the end index is inclusive.
193 | *
194 | * @param start The start index
195 | * @param end The end index
196 | * @param makeOneIndexed Whether the returned Range should be 1-indexed or 0-indexed.
197 | * @returns The Range object, or null if the indices are invalid.
198 | */
199 | public range(
200 | start: number,
201 | end: number,
202 | makeOneIndexed: boolean = false
203 | ): Range | null {
204 | let lcStart = this.lcAtIndex(start, makeOneIndexed);
205 | let lcEnd = this.lcAtIndex(end, makeOneIndexed);
206 |
207 | if (lcStart === null || lcEnd === null) {
208 | return null;
209 | }
210 |
211 | return {
212 | start: {
213 | line: lcStart[0],
214 | character: lcStart[1],
215 | },
216 | end: {
217 | line: lcEnd[0],
218 | character: lcEnd[1],
219 | },
220 | };
221 | }
222 |
223 | public rangeOfNode(ctx: ParserRuleContext): Range | null {
224 | let pos = getIx(ctx);
225 | return this.range(pos.start, pos.end);
226 | }
227 |
228 | public rangeOfToken(ctx: ParserRuleContext, token: string): Range | null {
229 | const node = (ctx as any)[token]() as TerminalNode;
230 | return this.range(node.symbol.startIndex, node.symbol.stopIndex + 1);
231 | }
232 | }
233 |
234 | export function getIx(ctx: ParserRuleContext): TextIndices {
235 | let start = ctx.start.startIndex;
236 | let end = ctx.stop?.stopIndex || ctx.start.stopIndex;
237 | let length = end - start + 1;
238 |
239 | return {
240 | start,
241 | end: start + length,
242 | };
243 | }
244 |
245 | /**
246 | * Returns the start and end indices of the given node.
247 | */
248 | export interface TextIndices {
249 | start: number;
250 | end: number;
251 | }
252 |
253 | /**
254 | * Compatible with LSP's Range object -- 0-indexed.
255 | */
256 | export interface Range {
257 | start: {
258 | line: number;
259 | character: number;
260 | };
261 |
262 | end: {
263 | line: number;
264 | character: number;
265 | };
266 | }
267 |
--------------------------------------------------------------------------------
/src/parser/validation.ts:
--------------------------------------------------------------------------------
1 | // import { CWScriptParserListener } from '../grammar/CWScriptParserListener';
2 | // import * as P from '../grammar/CWScriptParser';
3 | //
4 | // import { SymbolTable } from '../util/symbol-table';
5 | // import { ANTLRErrorListener, ParserRuleContext } from 'antlr4ts';
6 | // import { Diagnostic, DiagnosticSeverity } from 'vscode-languageserver';
7 | // import { getPosition, TextView } from '../util/position';
8 | // import { SourceFileContext } from '../grammar/CWScriptParser';
9 | // import { ParseTreeWalker } from 'antlr4ts/tree/ParseTreeWalker';
10 | // import { RecognitionException } from 'antlr4ts/RecognitionException';
11 | //
12 | // export abstract class CWSDiagnosticsCollector {
13 | // public diagnostics: Diagnostic[] = [];
14 | //
15 | // public get errors(): Diagnostic[] {
16 | // return this.diagnostics.filter(
17 | // (d) => d.severity === DiagnosticSeverity.Error
18 | // );
19 | // }
20 | //
21 | // public get warnings(): Diagnostic[] {
22 | // return this.diagnostics.filter(
23 | // (d) => d.severity === DiagnosticSeverity.Warning
24 | // );
25 | // }
26 | //
27 | // public get infos(): Diagnostic[] {
28 | // return this.diagnostics.filter(
29 | // (d) => d.severity === DiagnosticSeverity.Information
30 | // );
31 | // }
32 | //
33 | // public get hints(): Diagnostic[] {
34 | // return this.diagnostics.filter(
35 | // (d) => d.severity === DiagnosticSeverity.Hint
36 | // );
37 | // }
38 | // }
39 | //
40 | // export class CWSSyntaxErrorListener
41 | // extends CWSDiagnosticsCollector
42 | // implements ANTLRErrorListener
43 | // {
44 | // public diagnostics: Diagnostic[] = [];
45 | //
46 | // syntaxError(
47 | // recognizer: any,
48 | // offendingSymbol: any,
49 | // line: number,
50 | // charPositionInLine: number,
51 | // msg: string,
52 | // e: RecognitionException | undefined
53 | // ) {
54 | // this.diagnostics.push({
55 | // severity: DiagnosticSeverity.Error,
56 | // message: 'SyntaxError: ' + msg,
57 | // range: {
58 | // start: { line: line - 1, character: charPositionInLine },
59 | // end: { line: line - 1, character: charPositionInLine },
60 | // },
61 | // });
62 | // }
63 | // }
64 | //
65 | // export class CWSValidation
66 | // extends CWSDiagnosticsCollector
67 | // implements CWScriptParserListener
68 | // {
69 | // constructor(public env: any) {
70 | // super();
71 | // }
72 | //
73 | // enterEveryRule(ctx: ParserRuleContext) {}
74 | //
75 | // exitEveryRule(ctx: ParserRuleContext) {}
76 | //
77 | // public isInside(ruleName: string): boolean {
78 | // return this.validator.isInside(ruleName);
79 | // }
80 | //
81 | // public get scope(): SymbolTable {
82 | // return this.validator.scope;
83 | // }
84 | //
85 | // public pushScope(scope?: SymbolTable) {
86 | // this.validator.pushScope(scope);
87 | // }
88 | //
89 | // public popScope() {
90 | // return this.validator.popScope();
91 | // }
92 | // }
93 | //
94 | // export class CheckSymbolsDeclaredBeforeUse extends CWSValidation {
95 | // enterIdentExpr(ctx: P.IdentExprContext) {
96 | // if (!this.scope.hasSymbol(ctx.ident().text)) {
97 | // this.validator.addError(
98 | // ctx,
99 | // 'Symbol `' + ctx.text + '` used before definition.'
100 | // );
101 | // }
102 | // }
103 | //
104 | // // definitions below
105 | // enterIdentBinding_(ctx: P.IdentBinding_Context) {
106 | // this.scope.setSymbol(ctx._name.text, '');
107 | // }
108 | //
109 | // enterImportItemsStmt(ctx: P.ImportItemsStmtContext) {
110 | // ctx._items.forEach((sym) => {
111 | // this.scope.setSymbol(sym.text, '');
112 | // });
113 | // }
114 | //
115 | // enterParam(ctx: P.ParamContext) {
116 | // this.scope.setSymbol(ctx._name.text, '');
117 | // }
118 | //
119 | // enterInstantiateDefn(ctx: P.InstantiateDefnContext) {
120 | // this.scope.setSymbol('#instantiate', '');
121 | // }
122 | //
123 | // enterFnDefn(ctx: P.FnDefnContext) {
124 | // if (ctx._name) {
125 | // this.scope.setSymbol(ctx._name.text, '');
126 | // }
127 | // }
128 | //
129 | // enterStructDefn(ctx: P.StructDefnContext) {
130 | // if (ctx._name) {
131 | // this.scope.setSymbol(ctx._name.text, '');
132 | // }
133 | // }
134 | //
135 | // enterEnumDefn(ctx: P.EnumDefnContext) {
136 | // this.scope.setSymbol(ctx._name.text, '');
137 | // }
138 | // }
139 | //
140 | // export class CWSParseTreeValidator implements CWScriptParserListener {
141 | // public started: boolean = false;
142 | // public completed: boolean = false;
143 | // public diagnostics: Diagnostic[] = [];
144 | // public stages: ValidationStage[] = [];
145 | // protected scopes: SymbolTable[] = [];
146 | // protected depth: {
147 | // [key: string]: number;
148 | // } = {};
149 | //
150 | // public isInside(ruleName: string): boolean {
151 | // return this.depth[ruleName] > 0;
152 | // }
153 | //
154 | // public get scope(): SymbolTable {
155 | // return this.scopes[this.scopes.length - 1];
156 | // }
157 | //
158 | // public pushScope(scope?: SymbolTable) {
159 | // if (scope) {
160 | // this.scopes.push(scope);
161 | // } else {
162 | // this.scopes.push(new SymbolTable());
163 | // }
164 | // }
165 | //
166 | // public popScope() {
167 | // return this.scopes.pop();
168 | // }
169 | //
170 | // constructor(
171 | // public tree: SourceFileContext,
172 | // public sourceText: TextView,
173 | // stages: (new (...a: any[]) => ValidationStage)[] = []
174 | // ) {
175 | // this.scopes.push(new SymbolTable());
176 | // for (let stage of stages) {
177 | // this.stages.push(new stage(this));
178 | // }
179 | // }
180 | //
181 | // public hasErrors(): boolean {
182 | // return this.diagnostics.some(
183 | // (d) => d.severity === DiagnosticSeverity.Error
184 | // );
185 | // }
186 | //
187 | // public validate() {
188 | // this.started = true;
189 | // ParseTreeWalker.DEFAULT.walk(this, this.tree);
190 | // this.completed = true;
191 | // }
192 | //
193 | // enterEveryRule(ctx: ParserRuleContext) {
194 | // let ruleName = ctx.constructor.name.slice(0, -1 * 'Context'.length);
195 | // if (this.depth[ruleName] === undefined) {
196 | // this.depth[ruleName] = 0;
197 | // } else {
198 | // this.depth[ruleName]++;
199 | // }
200 | // for (let stage of this.stages) {
201 | // stage.enterEveryRule(ctx);
202 | // let fnName = `enter${ruleName}`;
203 | // if (fnName in stage) {
204 | // (stage as any)[fnName](ctx);
205 | // }
206 | // }
207 | // }
208 | //
209 | // exitEveryRule(ctx: ParserRuleContext) {
210 | // let ruleName = ctx.constructor.name.slice(0, -1 * 'Context'.length);
211 | // for (let stage of this.stages) {
212 | // stage.exitEveryRule(ctx);
213 | // let fnName = `exit${ruleName}`;
214 | // if (fnName in stage) {
215 | // (stage as any)[fnName](ctx);
216 | // }
217 | // }
218 | // this.depth[ruleName]--;
219 | // }
220 | //
221 | // public addError(ctx: ParserRuleContext, message: string) {
222 | // this.addDiagnostic(ctx, DiagnosticSeverity.Error, message);
223 | // }
224 | //
225 | // public addWarning(ctx: ParserRuleContext, message: string) {
226 | // this.addDiagnostic(ctx, DiagnosticSeverity.Warning, message);
227 | // }
228 | //
229 | // public addInfo(ctx: ParserRuleContext, message: string) {
230 | // this.addDiagnostic(ctx, DiagnosticSeverity.Information, message);
231 | // }
232 | //
233 | // public addHint(ctx: ParserRuleContext, message: string) {
234 | // this.addDiagnostic(ctx, DiagnosticSeverity.Hint, message);
235 | // }
236 | //
237 | // public addDiagnostic(
238 | // ctx: ParserRuleContext,
239 | // severity: DiagnosticSeverity,
240 | // message: string
241 | // ) {
242 | // let pos = getPosition(ctx);
243 | // let range = this.sourceText.range(pos.start, pos.end);
244 | // if (!range) {
245 | // throw new Error('Unable to get range for diagnostic.');
246 | // }
247 | // this.diagnostics.push({
248 | // severity,
249 | // message,
250 | // range,
251 | // });
252 | // }
253 | // }
254 |
--------------------------------------------------------------------------------
/dist/parser/validation.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 | // import { CWScriptParserListener } from '../grammar/CWScriptParserListener';
3 | // import * as P from '../grammar/CWScriptParser';
4 | //
5 | // import { SymbolTable } from '../util/symbol-table';
6 | // import { ANTLRErrorListener, ParserRuleContext } from 'antlr4ts';
7 | // import { Diagnostic, DiagnosticSeverity } from 'vscode-languageserver';
8 | // import { getPosition, TextView } from '../util/position';
9 | // import { SourceFileContext } from '../grammar/CWScriptParser';
10 | // import { ParseTreeWalker } from 'antlr4ts/tree/ParseTreeWalker';
11 | // import { RecognitionException } from 'antlr4ts/RecognitionException';
12 | //
13 | // export abstract class CWSDiagnosticsCollector {
14 | // public diagnostics: Diagnostic[] = [];
15 | //
16 | // public get errors(): Diagnostic[] {
17 | // return this.diagnostics.filter(
18 | // (d) => d.severity === DiagnosticSeverity.Error
19 | // );
20 | // }
21 | //
22 | // public get warnings(): Diagnostic[] {
23 | // return this.diagnostics.filter(
24 | // (d) => d.severity === DiagnosticSeverity.Warning
25 | // );
26 | // }
27 | //
28 | // public get infos(): Diagnostic[] {
29 | // return this.diagnostics.filter(
30 | // (d) => d.severity === DiagnosticSeverity.Information
31 | // );
32 | // }
33 | //
34 | // public get hints(): Diagnostic[] {
35 | // return this.diagnostics.filter(
36 | // (d) => d.severity === DiagnosticSeverity.Hint
37 | // );
38 | // }
39 | // }
40 | //
41 | // export class CWSSyntaxErrorListener
42 | // extends CWSDiagnosticsCollector
43 | // implements ANTLRErrorListener
44 | // {
45 | // public diagnostics: Diagnostic[] = [];
46 | //
47 | // syntaxError(
48 | // recognizer: any,
49 | // offendingSymbol: any,
50 | // line: number,
51 | // charPositionInLine: number,
52 | // msg: string,
53 | // e: RecognitionException | undefined
54 | // ) {
55 | // this.diagnostics.push({
56 | // severity: DiagnosticSeverity.Error,
57 | // message: 'SyntaxError: ' + msg,
58 | // range: {
59 | // start: { line: line - 1, character: charPositionInLine },
60 | // end: { line: line - 1, character: charPositionInLine },
61 | // },
62 | // });
63 | // }
64 | // }
65 | //
66 | // export class CWSValidation
67 | // extends CWSDiagnosticsCollector
68 | // implements CWScriptParserListener
69 | // {
70 | // constructor(public env: any) {
71 | // super();
72 | // }
73 | //
74 | // enterEveryRule(ctx: ParserRuleContext) {}
75 | //
76 | // exitEveryRule(ctx: ParserRuleContext) {}
77 | //
78 | // public isInside(ruleName: string): boolean {
79 | // return this.validator.isInside(ruleName);
80 | // }
81 | //
82 | // public get scope(): SymbolTable {
83 | // return this.validator.scope;
84 | // }
85 | //
86 | // public pushScope(scope?: SymbolTable) {
87 | // this.validator.pushScope(scope);
88 | // }
89 | //
90 | // public popScope() {
91 | // return this.validator.popScope();
92 | // }
93 | // }
94 | //
95 | // export class CheckSymbolsDeclaredBeforeUse extends CWSValidation {
96 | // enterIdentExpr(ctx: P.IdentExprContext) {
97 | // if (!this.scope.hasSymbol(ctx.ident().text)) {
98 | // this.validator.addError(
99 | // ctx,
100 | // 'Symbol `' + ctx.text + '` used before definition.'
101 | // );
102 | // }
103 | // }
104 | //
105 | // // definitions below
106 | // enterIdentBinding_(ctx: P.IdentBinding_Context) {
107 | // this.scope.setSymbol(ctx._name.text, '');
108 | // }
109 | //
110 | // enterImportItemsStmt(ctx: P.ImportItemsStmtContext) {
111 | // ctx._items.forEach((sym) => {
112 | // this.scope.setSymbol(sym.text, '');
113 | // });
114 | // }
115 | //
116 | // enterParam(ctx: P.ParamContext) {
117 | // this.scope.setSymbol(ctx._name.text, '');
118 | // }
119 | //
120 | // enterInstantiateDefn(ctx: P.InstantiateDefnContext) {
121 | // this.scope.setSymbol('#instantiate', '');
122 | // }
123 | //
124 | // enterFnDefn(ctx: P.FnDefnContext) {
125 | // if (ctx._name) {
126 | // this.scope.setSymbol(ctx._name.text, '');
127 | // }
128 | // }
129 | //
130 | // enterStructDefn(ctx: P.StructDefnContext) {
131 | // if (ctx._name) {
132 | // this.scope.setSymbol(ctx._name.text, '');
133 | // }
134 | // }
135 | //
136 | // enterEnumDefn(ctx: P.EnumDefnContext) {
137 | // this.scope.setSymbol(ctx._name.text, '');
138 | // }
139 | // }
140 | //
141 | // export class CWSParseTreeValidator implements CWScriptParserListener {
142 | // public started: boolean = false;
143 | // public completed: boolean = false;
144 | // public diagnostics: Diagnostic[] = [];
145 | // public stages: ValidationStage[] = [];
146 | // protected scopes: SymbolTable[] = [];
147 | // protected depth: {
148 | // [key: string]: number;
149 | // } = {};
150 | //
151 | // public isInside(ruleName: string): boolean {
152 | // return this.depth[ruleName] > 0;
153 | // }
154 | //
155 | // public get scope(): SymbolTable {
156 | // return this.scopes[this.scopes.length - 1];
157 | // }
158 | //
159 | // public pushScope(scope?: SymbolTable) {
160 | // if (scope) {
161 | // this.scopes.push(scope);
162 | // } else {
163 | // this.scopes.push(new SymbolTable());
164 | // }
165 | // }
166 | //
167 | // public popScope() {
168 | // return this.scopes.pop();
169 | // }
170 | //
171 | // constructor(
172 | // public tree: SourceFileContext,
173 | // public sourceText: TextView,
174 | // stages: (new (...a: any[]) => ValidationStage)[] = []
175 | // ) {
176 | // this.scopes.push(new SymbolTable());
177 | // for (let stage of stages) {
178 | // this.stages.push(new stage(this));
179 | // }
180 | // }
181 | //
182 | // public hasErrors(): boolean {
183 | // return this.diagnostics.some(
184 | // (d) => d.severity === DiagnosticSeverity.Error
185 | // );
186 | // }
187 | //
188 | // public validate() {
189 | // this.started = true;
190 | // ParseTreeWalker.DEFAULT.walk(this, this.tree);
191 | // this.completed = true;
192 | // }
193 | //
194 | // enterEveryRule(ctx: ParserRuleContext) {
195 | // let ruleName = ctx.constructor.name.slice(0, -1 * 'Context'.length);
196 | // if (this.depth[ruleName] === undefined) {
197 | // this.depth[ruleName] = 0;
198 | // } else {
199 | // this.depth[ruleName]++;
200 | // }
201 | // for (let stage of this.stages) {
202 | // stage.enterEveryRule(ctx);
203 | // let fnName = `enter${ruleName}`;
204 | // if (fnName in stage) {
205 | // (stage as any)[fnName](ctx);
206 | // }
207 | // }
208 | // }
209 | //
210 | // exitEveryRule(ctx: ParserRuleContext) {
211 | // let ruleName = ctx.constructor.name.slice(0, -1 * 'Context'.length);
212 | // for (let stage of this.stages) {
213 | // stage.exitEveryRule(ctx);
214 | // let fnName = `exit${ruleName}`;
215 | // if (fnName in stage) {
216 | // (stage as any)[fnName](ctx);
217 | // }
218 | // }
219 | // this.depth[ruleName]--;
220 | // }
221 | //
222 | // public addError(ctx: ParserRuleContext, message: string) {
223 | // this.addDiagnostic(ctx, DiagnosticSeverity.Error, message);
224 | // }
225 | //
226 | // public addWarning(ctx: ParserRuleContext, message: string) {
227 | // this.addDiagnostic(ctx, DiagnosticSeverity.Warning, message);
228 | // }
229 | //
230 | // public addInfo(ctx: ParserRuleContext, message: string) {
231 | // this.addDiagnostic(ctx, DiagnosticSeverity.Information, message);
232 | // }
233 | //
234 | // public addHint(ctx: ParserRuleContext, message: string) {
235 | // this.addDiagnostic(ctx, DiagnosticSeverity.Hint, message);
236 | // }
237 | //
238 | // public addDiagnostic(
239 | // ctx: ParserRuleContext,
240 | // severity: DiagnosticSeverity,
241 | // message: string
242 | // ) {
243 | // let pos = getPosition(ctx);
244 | // let range = this.sourceText.range(pos.start, pos.end);
245 | // if (!range) {
246 | // throw new Error('Unable to get range for diagnostic.');
247 | // }
248 | // this.diagnostics.push({
249 | // severity,
250 | // message,
251 | // range,
252 | // });
253 | // }
254 | // }
255 | //# sourceMappingURL=validation.js.map
--------------------------------------------------------------------------------
/dist/interpreter.d.ts:
--------------------------------------------------------------------------------
1 | import * as AST from './ast';
2 | import { SymbolTable } from './util/symbol-table';
3 | import { Type, Value, OptionT, Param, FnDefn, Arg, CWSString, ErrorMsg, ContractDefn, StructDefn, EnumDefn, ListT, StateMap, StateItem, CWSBool, Indexable, TupleT, MapKey, StructInstance, ListInstance, TupleInstance, EventMsg } from './stdlib';
4 | import { TextView } from './util/position';
5 | export declare function arg(val: Value, name?: string): Arg;
6 | export declare function args(a_pos?: Value[], a_named?: {
7 | [name: string]: Value;
8 | }): Arg[];
9 | export declare function idx(ix: number): Arg[];
10 | export interface CWSInterpreterContext {
11 | sources: {
12 | [filename: string]: string;
13 | };
14 | env?: {
15 | [globalName: string]: any;
16 | };
17 | }
18 | export declare enum ContextType {
19 | INSTANTIATE = 0,
20 | EXEC = 1,
21 | QUERY = 2
22 | }
23 | export interface Env {
24 | block: {
25 | height: number;
26 | time: number;
27 | chain_id: string;
28 | };
29 | contract: {
30 | address: string;
31 | };
32 | }
33 | export interface MessageInfo {
34 | sender: string;
35 | funds: Array<{
36 | denom: string;
37 | amount: string;
38 | }>;
39 | }
40 | export declare function buildCtxEnv(env: Env): StructInstance;
41 | export declare const CoinListT: ListT;
42 | export declare function buildCtxInfo(info: MessageInfo): StructInstance;
43 | export declare function buildCtxRes(): StructInstance;
44 | export declare function buildMutState(contract: ContractDefn): void;
45 | export declare function buildMutCtx(contract: ContractDefn, state: any, env: Env, info: MessageInfo): SymbolTable;
46 | export declare function buildQueryCtx(contract: ContractDefn, state: any, env: Env): SymbolTable;
47 | export declare class StateMapAccessor extends Value implements Indexable {
48 | state: ContractState;
49 | mapDefn: StateMap;
50 | prefix: string;
51 | mapKeys: MapKey[];
52 | ty: Type;
53 | default_: Value;
54 | constructor(state: ContractState, mapDefn: StateMap);
55 | getIndex(args: Arg[]): Value;
56 | setIndex(args: Arg[], val: Value): void;
57 | removeIndex(args: Arg[]): void;
58 | buildKey(args: Arg[]): string;
59 | }
60 | export declare const ContractStateT: Type>;
61 | export declare class ContractState extends Value {
62 | interpreter: CWSInterpreter;
63 | contract: ContractDefn;
64 | stateInfo: {
65 | [key: string]: StateItem | StateMap;
66 | };
67 | constructor(interpreter: CWSInterpreter, contract: ContractDefn);
68 | getSymbol(name: string): T;
69 | getOwnSymbol(name: string): T;
70 | firstTableWithSymbol(name: string): SymbolTable | undefined;
71 | }
72 | export declare class ContractInstance extends Value {
73 | interpreter: CWSInterpreter;
74 | ty: C;
75 | state: ContractState;
76 | constructor(interpreter: CWSInterpreter, ty: C);
77 | instantiate(env: Env, info: MessageInfo, args: Arg[]): any;
78 | exec(env: Env, info: MessageInfo, name: string, args: Arg[]): any;
79 | query(env: Env, name: string, args: Arg[]): Value | import("./stdlib").Impl>, any>;
80 | }
81 | export declare class CWSInterpreter extends SymbolTable {
82 | ctx: CWSInterpreterContext;
83 | visitor?: CWSInterpreterVisitor;
84 | constructor(ctx: CWSInterpreterContext);
85 | runCode(sourceText: string, file?: string): void;
86 | callFn(fn: FnDefn, args: Arg[], scope?: SymbolTable): Value | import("./stdlib").Impl>, any>;
87 | }
88 | export declare class Failure {
89 | error: Value;
90 | constructor(error: Value);
91 | }
92 | export declare class Return {
93 | value: Value;
94 | constructor(value: Value);
95 | }
96 | export declare class InterpreterError extends Error {
97 | constructor(message: string);
98 | }
99 | export declare class CWSInterpreterVisitor extends AST.CWSASTVisitor {
100 | interpreter: CWSInterpreter;
101 | sourceText: string;
102 | ctx: any;
103 | tv: TextView;
104 | scopes: SymbolTable[];
105 | private debugMode;
106 | get scope(): SymbolTable;
107 | firstTableWithSymbol(name: string): SymbolTable | undefined;
108 | hasSymbol(name: string): boolean;
109 | pushScope(scope: SymbolTable): void;
110 | popScope(): void;
111 | getSymbol(name: string): T;
112 | setSymbol(name: string, value: any): void;
113 | file: string;
114 | constructor(interpreter: CWSInterpreter, sourceText: string, file: string);
115 | makeError(message: string, node: AST.AST): InterpreterError;
116 | visit(node: AST.AST): T;
117 | visitSourceFile(node: AST.SourceFile): void;
118 | visitParam(node: AST.Param): Param;
119 | visitType(node: AST.AST): Type;
120 | visitInterfaceDefn(node: AST.InterfaceDefn): void;
121 | visitContractDefn(node: AST.ContractDefn): void;
122 | visitTypePath(node: AST.TypePath): Type;
123 | visitOptionT(node: AST.OptionT): OptionT;
124 | visitStructDefn(node: AST.ErrorDefn | AST.EventDefn | AST.StructDefn | AST.InstantiateDefn | AST.InstantiateDecl | AST.ExecDefn | AST.ExecDecl | AST.QueryDefn | AST.QueryDecl): StructDefn;
125 | visitEnumDefn(node: AST.EnumDefn): EnumDefn;
126 | visitListT(node: AST.ListT): ListT | TupleT;
127 | visitErrorDefn: (node: AST.ErrorDefn) => ErrorMsg;
128 | visitEventDefn: (node: AST.EventDefn) => EventMsg;
129 | visitMapKeyDefn(node: AST.MapKeyDefn): MapKey;
130 | visitFnDefn(node: AST.FnDefn): FnDefn;
131 | /**
132 | * This visits the function definition for the instantiate message.
133 | * @param node
134 | */
135 | visitInstantiateDefn(node: AST.InstantiateDefn): void;
136 | visitExecDefn(node: AST.ExecDefn): void;
137 | visitQueryDefn(node: AST.QueryDefn): void;
138 | visitBlock(node: AST.Block): Value;
139 | visitDebugStmt(node: AST.DebugStmt): void;
140 | visitLetStmt(node: AST.LetStmt): void;
141 | visitAssignStmt(node: AST.AssignStmt): void;
142 | visitIfStmt(node: AST.IfStmt): any;
143 | visitForStmt(node: AST.ForStmt): void;
144 | visitEmitStmt(node: AST.EmitStmt): void;
145 | visitExecStmt(node: AST.ExecStmt): void;
146 | visitDelegateExecStmt(node: AST.DelegateExecStmt): Value | import("./stdlib").Impl>, any>;
147 | visitInstantiateStmt(node: AST.InstantiateStmt): void;
148 | visitReturnStmt(node: AST.ReturnStmt): void;
149 | visitFailStmt(node: AST.FailStmt): void;
150 | visitArg(node: AST.Arg): Arg;
151 | visitDotExpr(node: AST.DotExpr): any;
152 | visitAsExpr(node: AST.AsExpr): void;
153 | visitIndexExpr(node: AST.IndexExpr): Value | import("./stdlib").Impl>, any>;
154 | visitDColonExpr(node: AST.DColonExpr): any;
155 | callMethod(obj: Value, method: string, argVals: Value[]): Value | import("./stdlib").Impl>, any>;
156 | callFn(fn: FnDefn, args: Arg[], scope?: SymbolTable): Value | import("./stdlib").Impl>, any>;
157 | visitFnCallExpr(node: AST.FnCallExpr): Value | import("./stdlib").Impl>, any> | import("./stdlib").Failure;
158 | executeBinOp(op: AST.Op, lhs: Value, rhs: Value): Value | import("./stdlib").Impl>, any>;
159 | visitBinOpExpr(node: AST.BinOpExpr): Value | import("./stdlib").Impl>, any>;
160 | visitAndExpr(node: AST.AndExpr): any;
161 | visitOrExpr(node: AST.OrExpr): any;
162 | visitIsExpr(node: AST.IsExpr): Value;
163 | visitInExpr(node: AST.InExpr): Value;
164 | visitNotExpr(node: AST.NotExpr): Value;
165 | visitNoneCheckExpr(node: AST.NoneCheckExpr): Value;
166 | visitTryCatchElseExpr(node: AST.TryCatchElseExpr): any;
167 | visitFailExpr(node: AST.FailExpr): Failure;
168 | visitClosure(node: AST.Closure): FnDefn | import("./stdlib").Impl>>;
169 | visitTupleExpr(node: AST.TupleExpr): TupleInstance | ListInstance | import("./stdlib").Impl>>;
170 | visitStructExpr(node: AST.StructExpr): StructInstance;
171 | visitUnitVariantExpr(node: AST.UnitVariantExpr): any;
172 | visitIdent(node: AST.Ident): any;
173 | visitGroupedExpr(node: AST.GroupedExpr): any;
174 | visitGrouped2Expr(node: AST.Grouped2Expr): any;
175 | visitStringLit(node: AST.StringLit): Value;
176 | visitIntLit(node: AST.IntLit): Value;
177 | visitDecLit(node: AST.DecLit): Value;
178 | visitBoolLit(node: AST.BoolLit): Value;
179 | visitNoneLit(node: AST.NoneLit): Value;
180 | }
181 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # `cwsc`: CWScript Compiler
2 |
3 | CWScript is a high-level programming language designed for writing smart contracts on the CosmWasm platform. It is focused on simplifying the process of creating smart contracts while maintaining compatibility with Rust and CosmWasm programming patterns. CWScript enforces a more constrained framework for writing smart contracts, allowing developers to build on a well-defined domain. This approach aims to streamline code organization, composability patterns, and the overall development experience.
4 |
5 | cwsc is written in TypeScript and requires Node.js v16 or later.
6 |
7 |
8 | * [`cwsc`: CWScript Compiler](#cwsc-cwscript-compiler)
9 | * [Features](#features)
10 | * [Installation](#installation)
11 | * [Usage](#usage)
12 | * [Examples](#examples)
13 | * [Hello World](#hello-world)
14 | * [Simple Token Contract](#simple-token-contract)
15 | * [Proxy Contract](#proxy-contract)
16 | * [AtomicOrderExample (Injective Protocol)](#atomicorderexample-injective-protocol)
17 | * [License](#license)
18 | * [Copyright](#copyright)
19 |
20 |
21 | ## Features
22 | - Simplified syntax, reducing syntactic noise and enhancing readability
23 | - High-level translation to idiomatic CosmWasm Rust patterns
24 | - Tooling-first approach, built for seamless integration with existing and new development tools
25 | - Designed to be extensible and compatible with Rust
26 | - Comprehensive documentation to guide you through the CWScript journey
27 |
28 |
29 | ## Installation
30 | **Initial release coming soon. Announcement will be made on official channels.**
31 | ##
32 | ## Usage
33 | Please refer to the official documentation for a complete guide on how to use CWScript and the cwsc compiler. Discover how to create, compile, and deploy smart contracts, and learn about the unique features of CWScript that simplify development and increase productivity.
34 |
35 | ## Examples
36 |
37 | ### Hello World
38 |
39 | ```rs
40 | contract HelloWorld {
41 | state {
42 | greeting: String
43 | }
44 |
45 | #instantiate(init_greeting: String) {
46 | $state.greeting = init_greeting
47 | }
48 |
49 | exec #update_greeting(new_greeting: String) {
50 | $state.greeting = new_greeting
51 | }
52 |
53 | query #get_greeting() -> String {
54 | return $state.greeting
55 | }
56 | }
57 | ```
58 |
59 | ### Simple Token Contract
60 |
61 | ```rs
62 | contract MyToken {
63 | state {
64 | total_supply: Uint128,
65 | balances[Address]: Uint128 = 0
66 | }
67 |
68 | #instantiate(initial_supply: Uint128) {
69 | let creator = $info.sender
70 | $state.total_supply = initial_supply
71 | $state.balances[creator] = initial_supply
72 | }
73 |
74 | exec #transfer(to: Address, amount: Uint128) {
75 | let sender = $info.sender
76 | let sender_balance = $state.balances[sender] ?? Uint128(0)
77 |
78 | assert!(sender_balance >= amount, "Insufficient balance")
79 |
80 | $state.balances[sender] = sender_balance - amount
81 | $state.balances[to] += amount
82 | }
83 |
84 | query #balance_of(address: Address) -> Uint128 {
85 | return $state.balances[address] ?? Uint128(0)
86 | }
87 |
88 | query #total_supply() -> Uint128 {
89 | return $state.total_supply
90 | }
91 | }
92 | ```
93 |
94 | ### Proxy Contract
95 |
96 | ```rs
97 | import { CW20 } from "standards/cw20"
98 |
99 | contract ProxyContract {
100 | state {
101 | target_token: Address
102 | }
103 |
104 | #instantiate(target_token_address: Address) {
105 | $state.target_token = target_token_address
106 | }
107 |
108 | exec #transfer_proxy(to: Address, amount: Uint128) {
109 | let sender = $info.sender
110 |
111 | // Call the transfer method of the target CW20 contract
112 | exec! CW20($state.target_token).#transfer(to, amount)
113 | }
114 |
115 | query #balance_of_proxy(address: Address) -> Uint128 {
116 | // Call the balance_of method of the target CW20 contract
117 | return query! CW20($state.target_token).#balance_of(address)
118 | }
119 | }
120 | ```
121 |
122 | ### AtomicOrderExample (Injective Protocol)
123 |
124 | ```rs
125 | import { SubaccountId, MarketId } from "injective/types"
126 | import { FPDecimal } from "injective/math"
127 | import { CW2 } from "standards/cw2"
128 |
129 | const CONTRACT_NAME = "crates.io:atomic-order-example"
130 | const CONTRACT_VERSION = "0.0.1"
131 |
132 | contract AtomicOrderExample extends CW2 {
133 |
134 | state {
135 | config: struct ContractConfigState {
136 | market_id: MarketId,
137 | owner: Address,
138 | contract_subaccount_id: SubaccountId,
139 | base_denom: String,
140 | quote_denom: String
141 | }
142 | swap_operation_state: struct SwapCacheState {
143 | sender_address: String,
144 | deposited_amount: Coin
145 | }
146 | }
147 |
148 | #instantiate(
149 | market_id: MarketId
150 | ) {
151 |
152 | let market = try {
153 | query! Exchange.#market(market_id)
154 | } else fail! "Market with id: {market_id} not found"
155 |
156 | let config = ContractConfigState {
157 | market_id,
158 | base_denom: market.base_denom,
159 | quote_denom: market.quote_denom,
160 | owner: $info.sender,
161 | contract_subaccount_id: SubaccountId($env.contract.address, 0),
162 | }
163 |
164 | CW2.set_contract_version!($, CONTRACT_NAME, CONTRACT_VERSION)
165 |
166 | // we've changed it to "config"
167 | $state.config = config
168 | emit event(method="instantiate", owner=$info.sender) // anonymous event
169 | }
170 |
171 | reply.success handle_atomic_order() {
172 | let dec_scale_factor = FPDecimal(1000000000000000000)
173 | let order_response = Exchange.#create_spot_market_order::parse_response!($data)
174 |
175 | let trade_data = order_response.results ?? fail! "No trade data in order response"
176 | let quantity = FPDecimal!(trade_data.quantity)
177 | let price = FPDecimal!(trade_data.price)
178 | let fee = FPDecimal!(trade_data.fee)
179 |
180 | let { config, cache } = $state
181 | let contract_address = $env.contract.address
182 | let subaccount_id = config.contract_subaccount_id
183 | let cache = $state.cache
184 | let purchased_coins = coin(quantity, config.base_denom)
185 | let pair = quantity * price + fee
186 | let leftover = cache.deposited_amount.amount - paid
187 |
188 |
189 | exec! Exchange.#withdraw(contract_address, subaccount_id, purchased_coins)
190 | exec! Exchange.#withdraw(contract_address, subaccount_id, leftover_coins)
191 | exec! Bank.#send(cache.sender_address, [purchased_coins, leftover_coins])
192 | }
193 |
194 | exec #swap_spot(quantity: FPDecimal, price: FPDecimal) {
195 | let { config } = $state
196 | let contract = $env.contract.address
197 | let subaccount_id = config.contract_subaccount_id
198 | let min_deposit = price quantity
199 |
200 | if $info.funds.is_empty() {
201 | fail! "No funds deposited!"
202 | }
203 |
204 | let message_deposit = FPDecimal!($info.funds[0].amount)
205 |
206 | if message_deposit < min_deposit {
207 | fail! "Deposit: {message_deposit} below min_deposit: {min_deposit}"
208 | }
209 |
210 | let order = SpotOrder(
211 | price, quantity, OrderType.#BuyAtomic, config.market_id, subaccount_id, contract
212 | )
213 |
214 | let coins = $info.funds[0]
215 |
216 | $state.swap_operation_state = SwapCacheState($info.sender, coins)
217 |
218 | exec! Exchange.#deposit(contract, subaccount_id, coins)
219 |
220 | @reply.success(handle_atomic_order)
221 | exec! Exchange.create_spot_market_order(contract, order)
222 | }
223 |
224 | }
225 | ```
226 |
227 | ## Related
228 |
229 | Checkout these related projects:
230 |
231 | * [@cosmology/telescope](https://github.com/cosmology-tech/telescope) Your Frontend Companion for Building with TypeScript with Cosmos SDK Modules.
232 | * [@cosmwasm/ts-codegen](https://github.com/CosmWasm/ts-codegen) Convert your CosmWasm smart contracts into dev-friendly TypeScript classes.
233 | * [chain-registry](https://github.com/cosmology-tech/chain-registry) Everything from token symbols, logos, and IBC denominations for all assets you want to support in your application.
234 | * [cosmos-kit](https://github.com/cosmology-tech/cosmos-kit) Experience the convenience of connecting with a variety of web3 wallets through a single, streamlined interface.
235 | * [create-cosmos-app](https://github.com/cosmology-tech/create-cosmos-app) Set up a modern Cosmos app by running one command.
236 | * [interchain-ui](https://github.com/cosmology-tech/interchain-ui) The Interchain Design System, empowering developers with a flexible, easy-to-use UI kit.
237 | * [starship](https://github.com/cosmology-tech/starship) Unified Testing and Development for the Interchain.
238 |
239 | ## Credits
240 |
241 | 🛠 Built by Cosmology — if you like our tools, please consider delegating to [our validator ⚛️](https://cosmology.zone/validator)
242 |
243 |
244 | ## Disclaimer
245 |
246 | AS DESCRIBED IN THE LICENSES, THE SOFTWARE IS PROVIDED “AS IS”, AT YOUR OWN RISK, AND WITHOUT WARRANTIES OF ANY KIND.
247 |
248 | No developer or entity involved in creating this software will be liable for any claims or damages whatsoever associated with your use, inability to use, or your interaction with other users of the code, including any direct, indirect, incidental, special, exemplary, punitive or consequential damages, or loss of profits, cryptocurrencies, tokens, or anything else of value.
249 |
250 | ## License
251 | CWScript, cwsc, and its bundled toolchain are licensed under the MIT License.
252 |
253 | ## Copyright
254 |
255 | Copyright © 2021-2023 Web, Inc.
256 |
--------------------------------------------------------------------------------