jslike 1.4.0 → 1.4.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,236 @@
1
+ // AST Node Constructors
2
+
3
+ export const Program = (body) => ({
4
+ type: 'Program',
5
+ body
6
+ });
7
+
8
+ export const Literal = (value) => ({
9
+ type: 'Literal',
10
+ value
11
+ });
12
+
13
+ export const Identifier = (name) => ({
14
+ type: 'Identifier',
15
+ name
16
+ });
17
+
18
+ export const BinaryExpression = (operator, left, right) => ({
19
+ type: 'BinaryExpression',
20
+ operator,
21
+ left,
22
+ right
23
+ });
24
+
25
+ export const UnaryExpression = (operator, argument, prefix = true) => ({
26
+ type: 'UnaryExpression',
27
+ operator,
28
+ argument,
29
+ prefix
30
+ });
31
+
32
+ export const UpdateExpression = (operator, argument, prefix = true) => ({
33
+ type: 'UpdateExpression',
34
+ operator,
35
+ argument,
36
+ prefix
37
+ });
38
+
39
+ export const AssignmentExpression = (operator, left, right) => ({
40
+ type: 'AssignmentExpression',
41
+ operator,
42
+ left,
43
+ right
44
+ });
45
+
46
+ export const LogicalExpression = (operator, left, right) => ({
47
+ type: 'LogicalExpression',
48
+ operator,
49
+ left,
50
+ right
51
+ });
52
+
53
+ export const ConditionalExpression = (test, consequent, alternate) => ({
54
+ type: 'ConditionalExpression',
55
+ test,
56
+ consequent,
57
+ alternate
58
+ });
59
+
60
+ export const CallExpression = (callee, args) => ({
61
+ type: 'CallExpression',
62
+ callee,
63
+ arguments: args
64
+ });
65
+
66
+ export const MemberExpression = (object, property, computed = false) => ({
67
+ type: 'MemberExpression',
68
+ object,
69
+ property,
70
+ computed
71
+ });
72
+
73
+ export const ArrayExpression = (elements) => ({
74
+ type: 'ArrayExpression',
75
+ elements
76
+ });
77
+
78
+ export const ObjectExpression = (properties) => ({
79
+ type: 'ObjectExpression',
80
+ properties
81
+ });
82
+
83
+ export const Property = (key, value, shorthand = false) => ({
84
+ type: 'Property',
85
+ key,
86
+ value,
87
+ shorthand
88
+ });
89
+
90
+ export const FunctionExpression = (id, params, body) => ({
91
+ type: 'FunctionExpression',
92
+ id,
93
+ params,
94
+ body
95
+ });
96
+
97
+ export const ArrowFunctionExpression = (params, body, expression = false) => ({
98
+ type: 'ArrowFunctionExpression',
99
+ params,
100
+ body,
101
+ expression
102
+ });
103
+
104
+ export const VariableDeclaration = (kind, declarations) => ({
105
+ type: 'VariableDeclaration',
106
+ kind,
107
+ declarations
108
+ });
109
+
110
+ export const VariableDeclarator = (id, init = null) => ({
111
+ type: 'VariableDeclarator',
112
+ id,
113
+ init
114
+ });
115
+
116
+ export const FunctionDeclaration = (id, params, body) => ({
117
+ type: 'FunctionDeclaration',
118
+ id,
119
+ params,
120
+ body
121
+ });
122
+
123
+ export const BlockStatement = (body) => ({
124
+ type: 'BlockStatement',
125
+ body
126
+ });
127
+
128
+ export const ExpressionStatement = (expression) => ({
129
+ type: 'ExpressionStatement',
130
+ expression
131
+ });
132
+
133
+ export const ReturnStatement = (argument = null) => ({
134
+ type: 'ReturnStatement',
135
+ argument
136
+ });
137
+
138
+ export const IfStatement = (test, consequent, alternate = null) => ({
139
+ type: 'IfStatement',
140
+ test,
141
+ consequent,
142
+ alternate
143
+ });
144
+
145
+ export const WhileStatement = (test, body) => ({
146
+ type: 'WhileStatement',
147
+ test,
148
+ body
149
+ });
150
+
151
+ export const DoWhileStatement = (body, test) => ({
152
+ type: 'DoWhileStatement',
153
+ body,
154
+ test
155
+ });
156
+
157
+ export const ForStatement = (init, test, update, body) => ({
158
+ type: 'ForStatement',
159
+ init,
160
+ test,
161
+ update,
162
+ body
163
+ });
164
+
165
+ export const ForInStatement = (left, right, body) => ({
166
+ type: 'ForInStatement',
167
+ left,
168
+ right,
169
+ body
170
+ });
171
+
172
+ export const ForOfStatement = (left, right, body) => ({
173
+ type: 'ForOfStatement',
174
+ left,
175
+ right,
176
+ body
177
+ });
178
+
179
+ export const BreakStatement = (label = null) => ({
180
+ type: 'BreakStatement',
181
+ label
182
+ });
183
+
184
+ export const ContinueStatement = (label = null) => ({
185
+ type: 'ContinueStatement',
186
+ label
187
+ });
188
+
189
+ export const ThrowStatement = (argument) => ({
190
+ type: 'ThrowStatement',
191
+ argument
192
+ });
193
+
194
+ export const TryStatement = (block, handler = null, finalizer = null) => ({
195
+ type: 'TryStatement',
196
+ block,
197
+ handler,
198
+ finalizer
199
+ });
200
+
201
+ export const CatchClause = (param, body) => ({
202
+ type: 'CatchClause',
203
+ param,
204
+ body
205
+ });
206
+
207
+ export const SwitchStatement = (discriminant, cases) => ({
208
+ type: 'SwitchStatement',
209
+ discriminant,
210
+ cases
211
+ });
212
+
213
+ export const SwitchCase = (test, consequent) => ({
214
+ type: 'SwitchCase',
215
+ test,
216
+ consequent
217
+ });
218
+
219
+ export const NewExpression = (callee, args) => ({
220
+ type: 'NewExpression',
221
+ callee,
222
+ arguments: args
223
+ });
224
+
225
+ export const ThisExpression = () => ({
226
+ type: 'ThisExpression'
227
+ });
228
+
229
+ export const SequenceExpression = (expressions) => ({
230
+ type: 'SequenceExpression',
231
+ expressions
232
+ });
233
+
234
+ export const EmptyStatement = () => ({
235
+ type: 'EmptyStatement'
236
+ });
@@ -0,0 +1,89 @@
1
+ #!/usr/bin/env node
2
+
3
+ import { readFile } from 'fs/promises';
4
+ import { stdin } from 'process';
5
+ import { execute } from '../index.js';
6
+
7
+ const args = process.argv.slice(2);
8
+
9
+ // Parse flags
10
+ const verbose = args.includes('--verbose');
11
+ const quiet = args.includes('--quiet');
12
+ const help = args.includes('--help') || args.includes('-h');
13
+
14
+ // Filter out flags to get file path
15
+ const filePath = args.find(arg => !arg.startsWith('--') && arg !== '-h');
16
+
17
+ if (help) {
18
+ console.log(`
19
+ Wang Language Runtime
20
+
21
+ Usage:
22
+ wang-run <file> Execute a Wang file
23
+ wang-run - Read from stdin
24
+ wang-run --help Show this help message
25
+
26
+ Options:
27
+ --verbose Show detailed execution information
28
+ --quiet Suppress extra output
29
+ -h, --help Show this help message
30
+
31
+ Examples:
32
+ wang-run script.wang
33
+ echo "console.log('test')" | wang-run -
34
+ `.trim());
35
+ process.exit(0);
36
+ }
37
+
38
+ async function readStdin() {
39
+ const chunks = [];
40
+ for await (const chunk of stdin) {
41
+ chunks.push(chunk);
42
+ }
43
+ return Buffer.concat(chunks).toString('utf8');
44
+ }
45
+
46
+ async function run() {
47
+ try {
48
+ let code;
49
+
50
+ if (filePath === '-') {
51
+ // Read from stdin
52
+ code = await readStdin();
53
+ } else if (filePath) {
54
+ // Read from file
55
+ code = await readFile(filePath, 'utf8');
56
+ } else {
57
+ console.error('Error: No input file specified');
58
+ console.error('Use --help for usage information');
59
+ process.exit(1);
60
+ }
61
+
62
+ if (verbose) {
63
+ console.log('🚀 Executing Wang code...');
64
+ }
65
+
66
+ // Execute the code
67
+ await execute(code);
68
+
69
+ if (verbose) {
70
+ console.log('✅ Execution completed successfully');
71
+ }
72
+
73
+ process.exit(0);
74
+ } catch (error) {
75
+ // For file not found errors, show generic error message
76
+ if (error.code === 'ENOENT') {
77
+ console.error('Error:', error.message);
78
+ } else {
79
+ console.error('❌ Execution failed:');
80
+ console.error(error.message);
81
+ if (verbose) {
82
+ console.error(error.stack);
83
+ }
84
+ }
85
+ process.exit(1);
86
+ }
87
+ }
88
+
89
+ run();
@@ -0,0 +1,87 @@
1
+ #!/usr/bin/env node
2
+
3
+ import { readFile } from 'fs/promises';
4
+ import { stdin } from 'process';
5
+ import { parse } from 'acorn';
6
+ import { isTopLevelAwait } from '../index.js';
7
+
8
+ const args = process.argv.slice(2);
9
+
10
+ // Parse flags
11
+ const showAst = args.includes('--ast');
12
+ const help = args.includes('--help') || args.includes('-h');
13
+
14
+ // Filter out flags to get file path
15
+ const filePath = args.find(arg => !arg.startsWith('--') && arg !== '-h');
16
+
17
+ if (help) {
18
+ console.log(`
19
+ Wang Language Validator
20
+
21
+ Usage:
22
+ wang-validate <file> Validate a Wang file
23
+ wang-validate - Read from stdin
24
+ wang-validate --help Show this help message
25
+
26
+ Options:
27
+ --ast Show the Abstract Syntax Tree
28
+ -h, --help Show this help message
29
+
30
+ Examples:
31
+ wang-validate script.wang
32
+ echo "let x = 1" | wang-validate -
33
+ wang-validate script.wang --ast
34
+ `.trim());
35
+ process.exit(0);
36
+ }
37
+
38
+ async function readStdin() {
39
+ const chunks = [];
40
+ for await (const chunk of stdin) {
41
+ chunks.push(chunk);
42
+ }
43
+ return Buffer.concat(chunks).toString('utf8');
44
+ }
45
+
46
+ async function validate() {
47
+ try {
48
+ let code;
49
+
50
+ if (filePath === '-') {
51
+ // Read from stdin
52
+ code = await readStdin();
53
+ } else if (filePath) {
54
+ // Read from file
55
+ code = await readFile(filePath, 'utf8');
56
+ } else {
57
+ console.error('Error: No input file specified');
58
+ console.error('Use --help for usage information');
59
+ process.exit(1);
60
+ }
61
+
62
+ // Check for top-level await
63
+ const hasAwait = isTopLevelAwait(code);
64
+
65
+ // Parse the code to validate syntax
66
+ const ast = parse(code, {
67
+ ecmaVersion: 'latest',
68
+ sourceType: hasAwait ? 'module' : 'script',
69
+ locations: true
70
+ });
71
+
72
+ console.log('✅ Valid Wang syntax');
73
+
74
+ if (showAst) {
75
+ console.log('\nAST:');
76
+ console.log(JSON.stringify(ast, null, 2));
77
+ }
78
+
79
+ process.exit(0);
80
+ } catch (error) {
81
+ console.error('❌ Invalid Wang syntax:');
82
+ console.error(error.message);
83
+ process.exit(1);
84
+ }
85
+ }
86
+
87
+ validate();
@@ -0,0 +1,234 @@
1
+ // Wang Language Definition for Monaco Editor
2
+ export const wangLanguage = {
3
+ defaultToken: 'invalid',
4
+ tokenPostfix: '.wang',
5
+
6
+ keywords: [
7
+ 'let',
8
+ 'const',
9
+ 'var',
10
+ 'if',
11
+ 'else',
12
+ 'for',
13
+ 'while',
14
+ 'do',
15
+ 'break',
16
+ 'continue',
17
+ 'return',
18
+ 'function',
19
+ 'class',
20
+ 'extends',
21
+ 'constructor',
22
+ 'async',
23
+ 'await',
24
+ 'import',
25
+ 'export',
26
+ 'from',
27
+ 'as',
28
+ 'try',
29
+ 'catch',
30
+ 'finally',
31
+ 'throw',
32
+ 'this',
33
+ 'super',
34
+ 'new',
35
+ 'typeof',
36
+ 'instanceof',
37
+ 'in',
38
+ 'of',
39
+ ],
40
+
41
+ typeKeywords: [],
42
+
43
+ operators: [
44
+ '=>',
45
+ '+=',
46
+ '-=',
47
+ '*=',
48
+ '/=',
49
+ '===',
50
+ '!==',
51
+ '==',
52
+ '!=',
53
+ '<=',
54
+ '>=',
55
+ '<<',
56
+ '>>',
57
+ '>>>',
58
+ '&&',
59
+ '||',
60
+ '??',
61
+ '?.',
62
+ '...',
63
+ '++',
64
+ '--',
65
+ '**',
66
+ '+',
67
+ '-',
68
+ '*',
69
+ '/',
70
+ '%',
71
+ '&',
72
+ '|',
73
+ '^',
74
+ '~',
75
+ '!',
76
+ '?',
77
+ ':',
78
+ '=',
79
+ '<',
80
+ '>',
81
+ ],
82
+
83
+ symbols: /[=><!~?:&|+\-*\/\^%]+/,
84
+
85
+ escapes: /\\(?:[abfnrtv\\"']|x[0-9A-Fa-f]{1,4}|u[0-9A-Fa-f]{4}|U[0-9A-Fa-f]{8})/,
86
+
87
+ tokenizer: {
88
+ root: [
89
+ // Identifiers and keywords
90
+ [
91
+ /[a-zA-Z_$][\w$]*/,
92
+ {
93
+ cases: {
94
+ '@keywords': 'keyword',
95
+ 'true|false|null|undefined': 'constant',
96
+ '@default': 'identifier',
97
+ },
98
+ },
99
+ ],
100
+
101
+ // Whitespace
102
+ { include: '@whitespace' },
103
+
104
+ // Delimiters and operators
105
+ [/[{}()\[\]]/, '@brackets'],
106
+ [/[<>](?!@symbols)/, '@brackets'],
107
+ [
108
+ /@symbols/,
109
+ {
110
+ cases: {
111
+ '@operators': 'operator',
112
+ '@default': '',
113
+ },
114
+ },
115
+ ],
116
+
117
+ // Numbers
118
+ [/\d*\.\d+([eE][\-+]?\d+)?/, 'number.float'],
119
+ [/0[xX][0-9a-fA-F]+/, 'number.hex'],
120
+ [/\d+/, 'number'],
121
+
122
+ // Delimiter
123
+ [/[;,.]/, 'delimiter'],
124
+
125
+ // Strings
126
+ [/"([^"\\]|\\.)*$/, 'string.invalid'],
127
+ [/'([^'\\]|\\.)*$/, 'string.invalid'],
128
+ [/"/, 'string', '@string_double'],
129
+ [/'/, 'string', '@string_single'],
130
+
131
+ // Template literals
132
+ [/`/, 'string.template', '@template'],
133
+
134
+ // Regular expressions
135
+ [/\/(?=([^\/\\]|\\.)+\/)/, 'regexp', '@regexp'],
136
+ ],
137
+
138
+ whitespace: [
139
+ [/[ \t\r\n]+/, ''],
140
+ [/\/\*/, 'comment', '@comment'],
141
+ [/\/\/.*$/, 'comment'],
142
+ ],
143
+
144
+ comment: [
145
+ [/[^\/*]+/, 'comment'],
146
+ [/\*\//, 'comment', '@pop'],
147
+ [/[\/*]/, 'comment'],
148
+ ],
149
+
150
+ string_double: [
151
+ [/[^\\"]+/, 'string'],
152
+ [/@escapes/, 'string.escape'],
153
+ [/\\./, 'string.escape.invalid'],
154
+ [/"/, 'string', '@pop'],
155
+ ],
156
+
157
+ string_single: [
158
+ [/[^\\']+/, 'string'],
159
+ [/@escapes/, 'string.escape'],
160
+ [/\\./, 'string.escape.invalid'],
161
+ [/'/, 'string', '@pop'],
162
+ ],
163
+
164
+ template: [
165
+ [/[^`\\$]+/, 'string.template'],
166
+ [/@escapes/, 'string.escape'],
167
+ [/\\./, 'string.escape.invalid'],
168
+ [/\${/, { token: 'delimiter.bracket', next: '@templateExpression' }],
169
+ [/`/, 'string.template', '@pop'],
170
+ ],
171
+
172
+ templateExpression: [[/}/, { token: 'delimiter.bracket', next: '@pop' }], { include: 'root' }],
173
+
174
+ regexp: [
175
+ [
176
+ /(\{)(\d+(?:,\d*)?)(\})/,
177
+ ['regexp.escape.control', 'regexp.escape.control', 'regexp.escape.control'],
178
+ ],
179
+ [/(\[)([^\]\\]|\\.)*(\])/, 'regexp.escape.control'],
180
+ [/(\()(\?:|\?=|\?!)/, ['regexp.escape.control', 'regexp.escape.control']],
181
+ [/[()]/, 'regexp.escape.control'],
182
+ [/@escapes/, 'regexp.escape'],
183
+ [/\\./, 'regexp.escape'],
184
+ [/\/[gimsuy]*/, { token: 'regexp', bracket: '@close', next: '@pop' }],
185
+ [/./, 'regexp'],
186
+ ],
187
+ },
188
+ };
189
+
190
+ // Register the language with Monaco
191
+ export function registerWangLanguage(monaco) {
192
+ monaco.languages.register({ id: 'wang' });
193
+ monaco.languages.setMonarchTokensProvider('wang', wangLanguage);
194
+
195
+ // Configuration for brackets and auto-closing
196
+ monaco.languages.setLanguageConfiguration('wang', {
197
+ comments: {
198
+ lineComment: '//',
199
+ blockComment: ['/*', '*/'],
200
+ },
201
+ brackets: [
202
+ ['{', '}'],
203
+ ['[', ']'],
204
+ ['(', ')'],
205
+ ],
206
+ autoClosingPairs: [
207
+ { open: '{', close: '}' },
208
+ { open: '[', close: ']' },
209
+ { open: '(', close: ')' },
210
+ { open: '"', close: '"', notIn: ['string'] },
211
+ { open: "'", close: "'", notIn: ['string'] },
212
+ { open: '`', close: '`', notIn: ['string'] },
213
+ { open: '/*', close: '*/' },
214
+ ],
215
+ surroundingPairs: [
216
+ { open: '{', close: '}' },
217
+ { open: '[', close: ']' },
218
+ { open: '(', close: ')' },
219
+ { open: '"', close: '"' },
220
+ { open: "'", close: "'" },
221
+ { open: '`', close: '`' },
222
+ ],
223
+ folding: {
224
+ markers: {
225
+ start: new RegExp('^\\s*//\\s*#?region\\b'),
226
+ end: new RegExp('^\\s*//\\s*#?endregion\\b'),
227
+ },
228
+ },
229
+ indentationRules: {
230
+ increaseIndentPattern: new RegExp('^.*(\\{[^}]*|\\([^)]*|\\[[^\\]]*)$'),
231
+ decreaseIndentPattern: new RegExp('^\\s*(\\}|\\)|\\])'),
232
+ },
233
+ });
234
+ }