naider 1.8.0 → 1.10.0

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.
package/README.md CHANGED
@@ -68,7 +68,7 @@ naide --tokens <file> # Print token stream
68
68
 
69
69
  ```
70
70
  $ naide
71
- NAIDE REPL v1.8.0 — type NAIDE code, see JavaScript output
71
+ NAIDE REPL v1.9.0 — type NAIDE code, see JavaScript output
72
72
  Type .exit to quit, .eval to toggle eval mode
73
73
 
74
74
  >>> str name = "hello"
package/bin/naide.js CHANGED
@@ -2,7 +2,7 @@
2
2
 
3
3
  import { readFileSync, writeFileSync, unlinkSync, watch as fsWatch, existsSync, mkdirSync, readdirSync, statSync } from 'fs';
4
4
  import { resolve, basename, extname, join, relative } from 'path';
5
- import { compile } from '../src/index.js';
5
+ import { compile, compileAsync } from '../src/index.js';
6
6
  import { spawn } from 'child_process';
7
7
 
8
8
  import { createRequire } from 'module';
@@ -76,6 +76,7 @@ const flags = {
76
76
  watch: false,
77
77
  debug: false,
78
78
  check: false,
79
+ target: 'node',
79
80
  };
80
81
 
81
82
  const files = [];
@@ -93,6 +94,7 @@ for (let i = 0; i < args.length; i++) {
93
94
  case '--watch': case '-w': flags.watch = true; break;
94
95
  case '--debug': case '-d': flags.debug = true; break;
95
96
  case '--check': flags.check = true; flags.run = false; break;
97
+ case '--target': case '-t': flags.target = args[++i]; break;
96
98
  default: files.push(arg);
97
99
  }
98
100
  }
@@ -151,7 +153,7 @@ if (files[0] === 'repl' || (files.length === 0 && !flags.help)) {
151
153
  const { createInterface } = await import('readline');
152
154
  const { transpile } = await import('../src/index.js');
153
155
 
154
- console.log(`\n NAIDE REPL v1.8.0 — type NAIDE code, see JavaScript output`);
156
+ console.log(`\n NAIDE REPL v1.10.0 — type NAIDE code, see JavaScript output`);
155
157
  console.log(` Type .exit to quit, .eval to toggle eval mode\n`);
156
158
 
157
159
  const rl = createInterface({
@@ -290,7 +292,7 @@ if (files[0] === 'init') {
290
292
  writeFileSync(resolve(dir, 'package.json'), JSON.stringify({
291
293
  name, version: '1.0.0', type: 'module',
292
294
  scripts: { start: 'naide app.naide', dev: 'naide -w app.naide', build: 'naide --emit app.naide -o dist/app.mjs' },
293
- dependencies: { naider: '^1.8.0' }
295
+ dependencies: { naider: '^1.9.0' }
294
296
  }, null, 2) + '\n');
295
297
  }
296
298
 
@@ -681,6 +683,11 @@ if (flags.help) {
681
683
  naide -w <file.naide> Watch mode (auto-restart on changes)
682
684
  naide -d <file> Debug mode (Node.js inspector)
683
685
 
686
+ Targets:
687
+ node Node.js / JavaScript (default)
688
+ bun Bun-optimized JavaScript
689
+ python Python (Flask for servers)
690
+
684
691
  Modes:
685
692
  .naide Standard NAIDE (~40% fewer tokens than JS)
686
693
  .nx NAIDE-X extreme (~80% fewer tokens than JS)
@@ -691,6 +698,7 @@ if (flags.help) {
691
698
  -x Force NAIDE-X mode
692
699
  -w, --watch Watch mode: restart on file changes
693
700
  -d, --debug Start with Node.js debugger (--inspect-brk)
701
+ -t, --target Compile target: node (default), bun, python/py
694
702
  --check Type-check files without running
695
703
  --mid Show intermediate NAIDE v1 (X mode only)
696
704
  --ast Print AST
@@ -772,7 +780,10 @@ for (const file of files) {
772
780
  continue;
773
781
  }
774
782
 
775
- const result = compile(source, { mode, runtimePath, sourceFile: file, typeCheck: flags.check });
783
+ const useAsync = flags.target !== 'node';
784
+ const result = useAsync
785
+ ? await compileAsync(source, { mode, runtimePath, sourceFile: file, typeCheck: flags.check, target: flags.target })
786
+ : compile(source, { mode, runtimePath, sourceFile: file, typeCheck: flags.check });
776
787
 
777
788
  if (flags.check) {
778
789
  const { typeErrors } = result;
@@ -794,17 +805,39 @@ for (const file of files) {
794
805
  continue;
795
806
  }
796
807
 
808
+ const outputCode = result.code || result.js;
809
+ const outputExt = flags.target === 'python' || flags.target === 'py' ? '.py' : '.mjs';
810
+
797
811
  if (flags.output) {
798
- writeFileSync(flags.output, result.js, 'utf-8');
812
+ writeFileSync(flags.output, outputCode, 'utf-8');
799
813
  console.log(`Written to ${flags.output}`);
800
814
  continue;
801
815
  }
802
816
 
803
817
  if (flags.emit) {
804
- console.log(result.js);
818
+ console.log(outputCode);
819
+ continue;
820
+ }
821
+
822
+ if (flags.target === 'python' || flags.target === 'py') {
823
+ const outFile = flags.output || resolve(basename(file, ext) + '.py');
824
+ writeFileSync(outFile, outputCode, 'utf-8');
825
+ console.log(` ${file} → ${basename(outFile)} (Python)`);
805
826
  continue;
806
827
  }
807
828
 
829
+ if (flags.target === 'bun') {
830
+ const tempFile = resolve(`.naide_tmp_${basename(file, ext)}.mjs`);
831
+ writeFileSync(tempFile, outputCode, 'utf-8');
832
+ console.log(`[NAIDE] Running with Bun — ${file}`);
833
+ const bunChild = spawn('bun', ['run', tempFile], { stdio: 'inherit', shell: true });
834
+ bunChild.on('close', (code) => {
835
+ try { unlinkSync(tempFile); } catch {}
836
+ process.exit(code || 0);
837
+ });
838
+ await new Promise(() => {});
839
+ }
840
+
808
841
  // Run mode
809
842
  const tempFile = resolve(`.naide_tmp_${basename(file, ext)}.mjs`);
810
843
  writeFileSync(tempFile, result.js, 'utf-8');
package/lsp/server.js CHANGED
@@ -1,6 +1,7 @@
1
1
  import { compile } from '../src/index.js';
2
2
 
3
3
  const documents = new Map();
4
+ const symbolIndex = new Map();
4
5
  let buffer = '';
5
6
 
6
7
  process.stdin.setEncoding('utf-8');
@@ -37,6 +38,8 @@ function handleMessage(msg) {
37
38
  textDocumentSync: 1,
38
39
  completionProvider: { triggerCharacters: ['.', '"'] },
39
40
  hoverProvider: true,
41
+ definitionProvider: true,
42
+ referencesProvider: true,
40
43
  }
41
44
  });
42
45
  break;
@@ -68,6 +71,14 @@ function handleMessage(msg) {
68
71
  respond(msg.id, getHover(msg.params));
69
72
  break;
70
73
 
74
+ case 'textDocument/definition':
75
+ respond(msg.id, getDefinition(msg.params));
76
+ break;
77
+
78
+ case 'textDocument/references':
79
+ respond(msg.id, getReferences(msg.params));
80
+ break;
81
+
71
82
  case 'shutdown':
72
83
  respond(msg.id, null);
73
84
  break;
@@ -133,9 +144,138 @@ function validateDocument(uri) {
133
144
  });
134
145
  }
135
146
 
147
+ indexSymbols(uri, text);
136
148
  notify('textDocument/publishDiagnostics', { uri, diagnostics });
137
149
  }
138
150
 
151
+ function indexSymbols(uri, text) {
152
+ const symbols = { definitions: new Map(), references: new Map() };
153
+ const lines = text.split('\n');
154
+
155
+ for (let i = 0; i < lines.length; i++) {
156
+ const line = lines[i];
157
+ const trimmed = line.trimStart();
158
+
159
+ const fnMatch = trimmed.match(/^(?:pub\s+)?(?:fn\.async|fn)\s+(\w+)\s*\(/);
160
+ if (fnMatch) {
161
+ const name = fnMatch[1];
162
+ const col = line.indexOf(name);
163
+ symbols.definitions.set(name, { line: i, col, kind: 'function' });
164
+ }
165
+
166
+ const varMatch = trimmed.match(/^(?:pub\s+)?(?:mut\s+)?(?:str|int|num|bool|list|map|any|json|void)\s+(\w+)\s*=/);
167
+ if (varMatch) {
168
+ const name = varMatch[1];
169
+ const col = line.indexOf(name);
170
+ symbols.definitions.set(name, { line: i, col, kind: 'variable' });
171
+ }
172
+
173
+ const modelMatch = trimmed.match(/^model\s+(\w+)/);
174
+ if (modelMatch) {
175
+ const name = modelMatch[1];
176
+ const col = line.indexOf(name);
177
+ symbols.definitions.set(name, { line: i, col, kind: 'class' });
178
+ }
179
+
180
+ const schemaMatch = trimmed.match(/^schema\s+(\w+)/);
181
+ if (schemaMatch) {
182
+ const name = schemaMatch[1];
183
+ const col = line.indexOf(name);
184
+ symbols.definitions.set(name, { line: i, col, kind: 'schema' });
185
+ }
186
+
187
+ const promptMatch = trimmed.match(/^prompt\s+(\w+)/);
188
+ if (promptMatch) {
189
+ const name = promptMatch[1];
190
+ const col = line.indexOf(name);
191
+ symbols.definitions.set(name, { line: i, col, kind: 'prompt' });
192
+ }
193
+
194
+ for (const def of symbols.definitions.keys()) {
195
+ const re = new RegExp(`\\b${def}\\b`, 'g');
196
+ let m;
197
+ while ((m = re.exec(line)) !== null) {
198
+ if (i === symbols.definitions.get(def)?.line && m.index === symbols.definitions.get(def)?.col) continue;
199
+ if (!symbols.references.has(def)) symbols.references.set(def, []);
200
+ symbols.references.get(def).push({ line: i, col: m.index });
201
+ }
202
+ }
203
+ }
204
+
205
+ symbolIndex.set(uri, symbols);
206
+ }
207
+
208
+ function getWordAtPosition(text, line, col) {
209
+ const lines = text.split('\n');
210
+ if (line >= lines.length) return null;
211
+ const lineText = lines[line];
212
+ let start = col, end = col;
213
+ while (start > 0 && /\w/.test(lineText[start - 1])) start--;
214
+ while (end < lineText.length && /\w/.test(lineText[end])) end++;
215
+ return lineText.slice(start, end) || null;
216
+ }
217
+
218
+ function getDefinition(params) {
219
+ const uri = params.textDocument.uri;
220
+ const text = documents.get(uri);
221
+ if (!text) return null;
222
+
223
+ const word = getWordAtPosition(text, params.position.line, params.position.character);
224
+ if (!word) return null;
225
+
226
+ const symbols = symbolIndex.get(uri);
227
+ if (!symbols) return null;
228
+
229
+ const def = symbols.definitions.get(word);
230
+ if (!def) return null;
231
+
232
+ return {
233
+ uri,
234
+ range: {
235
+ start: { line: def.line, character: def.col },
236
+ end: { line: def.line, character: def.col + word.length },
237
+ },
238
+ };
239
+ }
240
+
241
+ function getReferences(params) {
242
+ const uri = params.textDocument.uri;
243
+ const text = documents.get(uri);
244
+ if (!text) return [];
245
+
246
+ const word = getWordAtPosition(text, params.position.line, params.position.character);
247
+ if (!word) return [];
248
+
249
+ const symbols = symbolIndex.get(uri);
250
+ if (!symbols) return [];
251
+
252
+ const results = [];
253
+
254
+ const def = symbols.definitions.get(word);
255
+ if (def) {
256
+ results.push({
257
+ uri,
258
+ range: {
259
+ start: { line: def.line, character: def.col },
260
+ end: { line: def.line, character: def.col + word.length },
261
+ },
262
+ });
263
+ }
264
+
265
+ const refs = symbols.references.get(word) || [];
266
+ for (const ref of refs) {
267
+ results.push({
268
+ uri,
269
+ range: {
270
+ start: { line: ref.line, character: ref.col },
271
+ end: { line: ref.line, character: ref.col + word.length },
272
+ },
273
+ });
274
+ }
275
+
276
+ return results;
277
+ }
278
+
139
279
  function getCompletions() {
140
280
  const keywords = [
141
281
  'fn', 'ret', 'if', 'elif', 'else', 'each', 'for', 'while', 'match',
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "naider",
3
- "version": "1.8.0",
3
+ "version": "1.10.0",
4
4
  "description": "NAIDE - Node AI Development Environment. AI-specialized language with built-in server, auth, DB, SQL, AI/LLM, WebSocket, and more — transpiles to Node.js.",
5
5
  "main": "src/index.js",
6
6
  "exports": {