future-lang 0.3.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/ARCHITECTURE.md +424 -0
- package/MIGRATION.md +365 -0
- package/README.md +370 -0
- package/ROADMAP.md +263 -0
- package/examples/adult.future +8 -0
- package/examples/api.future +11 -0
- package/examples/assistant.future +8 -0
- package/examples/browser-demo.html +164 -0
- package/examples/greet.future +7 -0
- package/examples/hello.future +1 -0
- package/examples/math.future +8 -0
- package/examples/mini-app.html +301 -0
- package/examples/smarthome.future +10 -0
- package/future-browser.js +102 -0
- package/future-playground.html +650 -0
- package/package.json +27 -0
- package/runtime/ai.js +92 -0
- package/runtime/browser.js +458 -0
- package/runtime/device.js +36 -0
- package/runtime/home.js +19 -0
- package/runtime/http.js +32 -0
- package/runtime/index.js +403 -0
- package/runtime/lsp-metadata.js +104 -0
- package/runtime/math.js +16 -0
- package/runtime/memory.js +61 -0
- package/runtime/mqtt.js +49 -0
- package/runtime/providers/anthropic.js +59 -0
- package/runtime/providers/index.js +93 -0
- package/runtime/providers/openai-compat.js +85 -0
- package/runtime/providers/util.js +70 -0
- package/runtime/rag/chunker.js +65 -0
- package/runtime/rag/pipeline.js +86 -0
- package/runtime/rag/vector-store.js +119 -0
- package/runtime/rag.js +94 -0
- package/runtime/schedule.js +77 -0
- package/runtime/system.js +101 -0
- package/runtime/tts.js +38 -0
- package/runtime/vision.js +85 -0
- package/server.js +42 -0
- package/src/ast.js +202 -0
- package/src/cli.js +391 -0
- package/src/errors.js +21 -0
- package/src/formatter.js +48 -0
- package/src/generator.js +457 -0
- package/src/index.js +48 -0
- package/src/lexer.js +248 -0
- package/src/parser.js +469 -0
package/MIGRATION.md
ADDED
|
@@ -0,0 +1,365 @@
|
|
|
1
|
+
# Future — Migration & Changelog
|
|
2
|
+
|
|
3
|
+
All releases are **additive only**. No existing Future program has ever required changes to compile and run.
|
|
4
|
+
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
## v0.3.1 → v0.3.2 (current — Phase 7: General-Purpose Programming)
|
|
8
|
+
|
|
9
|
+
**No breaking changes.**
|
|
10
|
+
|
|
11
|
+
### New built-in: `len(x)`
|
|
12
|
+
|
|
13
|
+
```future
|
|
14
|
+
items = [1, 2, 3, 4, 5]
|
|
15
|
+
print len(items) # 5
|
|
16
|
+
print len("hello") # 5
|
|
17
|
+
obj = { a: 1 b: 2 }
|
|
18
|
+
print len(obj) # 2
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
`len()` is a sync built-in — it never triggers ASYNC mode on its own. Programs that only use `len()` still compile to plain synchronous JavaScript. Works on arrays, strings, and objects (falls back to `Object.keys().length` for objects).
|
|
22
|
+
|
|
23
|
+
### New module: `math`
|
|
24
|
+
|
|
25
|
+
```future
|
|
26
|
+
print math.round(3.7) # 4
|
|
27
|
+
print math.floor(3.9) # 3
|
|
28
|
+
print math.ceil(3.1) # 4
|
|
29
|
+
print math.abs(-5) # 5
|
|
30
|
+
print math.sqrt(16) # 4
|
|
31
|
+
print math.pow(2, 8) # 256
|
|
32
|
+
print math.min(1, 5, 3) # 1
|
|
33
|
+
print math.max(1, 5, 3) # 5
|
|
34
|
+
print math.random() # 0.0–1.0
|
|
35
|
+
print math.log(math.e) # 1
|
|
36
|
+
print math.pi # 3.14159...
|
|
37
|
+
print math.e # 2.71828...
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
`math.*` calls are capability calls — they trigger ASYNC mode and are routed through `__rt.math.*`. `math.pi` and `math.e` are constants (property access, not function calls).
|
|
41
|
+
|
|
42
|
+
### New built-in: `input(prompt)`
|
|
43
|
+
|
|
44
|
+
```future
|
|
45
|
+
name = input("What is your name? ")
|
|
46
|
+
print "Hello, {name}!"
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
`input()` is an async built-in — it always triggers ASYNC mode. In Node.js it reads a line from stdin via `readline`. In the browser it calls `window.prompt()`.
|
|
50
|
+
|
|
51
|
+
### Namespace references inside strings
|
|
52
|
+
|
|
53
|
+
String interpolation now correctly handles namespace property access:
|
|
54
|
+
|
|
55
|
+
```future
|
|
56
|
+
print "Pi is {math.pi}"
|
|
57
|
+
print "Euler: {math.e}"
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
Previously, `{math.pi}` inside a string literal would emit `${math.pi}` — a ReferenceError at runtime because `math` is not a JS variable. Now it emits `${__rt.math.pi}` in ASYNC mode.
|
|
61
|
+
|
|
62
|
+
The fix also triggers ASYNC mode detection for programs where the only namespace usage is inside a string.
|
|
63
|
+
|
|
64
|
+
### Browser runtime (`future-browser.js`)
|
|
65
|
+
|
|
66
|
+
The browser runtime bundles the full compiler and a browser-compatible capability set. It can be loaded with a single `<script>` tag.
|
|
67
|
+
|
|
68
|
+
```html
|
|
69
|
+
<script type="module" src="future-browser.js"></script>
|
|
70
|
+
|
|
71
|
+
<script type="module">
|
|
72
|
+
import Future from './future-browser.js'
|
|
73
|
+
Future.configure({ proxy: '/api/ai' })
|
|
74
|
+
Future.runtime.print = (...args) =>
|
|
75
|
+
document.getElementById('output').textContent += args.join(' ') + '\n'
|
|
76
|
+
</script>
|
|
77
|
+
|
|
78
|
+
<script type="future">
|
|
79
|
+
scores = [85, 92, 78]
|
|
80
|
+
n = len(scores)
|
|
81
|
+
avg = math.round((85 + 92 + 78) / n)
|
|
82
|
+
print "Average: {avg}"
|
|
83
|
+
</script>
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
API key security options:
|
|
87
|
+
- **Proxy mode** (`Future.configure({ proxy: '/api/ai' })`) — key stays on your server.
|
|
88
|
+
- **Demo mode** (`Future.configure({ provider: 'openai', apiKey: 'sk-...' })`) — key visible in source, dev/demos only.
|
|
89
|
+
|
|
90
|
+
### Internal compiler changes
|
|
91
|
+
|
|
92
|
+
- `NAMESPACES` in `src/generator.js` — `'math'` added.
|
|
93
|
+
- `usesRuntime()` — now detects `input()` calls, namespace `MemberExpression` nodes, and `{namespace.prop}` patterns inside `StringLiteral` values.
|
|
94
|
+
- `usesBuiltin(node, name)` — new helper to detect specific built-in call sites (used for `len`).
|
|
95
|
+
- `Generator.genStringLiteral()` — promoted from a standalone function to an instance method, gains access to `this.asyncMode` and `NAMESPACES` to correctly prefix namespace refs with `__rt.`.
|
|
96
|
+
- `genCall()` — special-cases `len` → `__len(args)` and `input` → `await __rt.input(args)`.
|
|
97
|
+
- `runtime/math.js` — new module, 12 exports (10 functions + 2 constants).
|
|
98
|
+
- `runtime/index.js` — `math` added to module list + manifest; `runtime.input` added (readline-based).
|
|
99
|
+
- `runtime/browser.js` — `math` module and `input` function added; `browserRuntime` object updated.
|
|
100
|
+
|
|
101
|
+
### Reserved keywords added
|
|
102
|
+
|
|
103
|
+
- `math` — now a reserved namespace identifier (cannot be used as a variable name).
|
|
104
|
+
- `input` — built-in identifier (shadowing it with a user variable is not recommended).
|
|
105
|
+
|
|
106
|
+
---
|
|
107
|
+
|
|
108
|
+
## v0.3.0 → v0.3.1 (Phase 6: Core Language)
|
|
109
|
+
|
|
110
|
+
**No breaking changes.**
|
|
111
|
+
|
|
112
|
+
### New language features
|
|
113
|
+
|
|
114
|
+
#### List literals
|
|
115
|
+
|
|
116
|
+
```future
|
|
117
|
+
items = [1, 2, 3]
|
|
118
|
+
names = ["Alice", "Bob"]
|
|
119
|
+
empty = []
|
|
120
|
+
```
|
|
121
|
+
|
|
122
|
+
Emits a standard JS array literal. Elements can be any expression.
|
|
123
|
+
|
|
124
|
+
#### `for item in list ... end`
|
|
125
|
+
|
|
126
|
+
```future
|
|
127
|
+
for name in names
|
|
128
|
+
print "Hello {name}"
|
|
129
|
+
end
|
|
130
|
+
```
|
|
131
|
+
|
|
132
|
+
Compiles to `for (const item of list) { … }`. The loop variable is block-scoped (`const`), not hoisted.
|
|
133
|
+
|
|
134
|
+
#### `try ... catch err ... end`
|
|
135
|
+
|
|
136
|
+
```future
|
|
137
|
+
try
|
|
138
|
+
result = ai.ask("question")
|
|
139
|
+
catch err
|
|
140
|
+
print "Error: {err}"
|
|
141
|
+
end
|
|
142
|
+
```
|
|
143
|
+
|
|
144
|
+
Compiles to a standard JS `try/catch`. The catch variable is block-scoped — not hoisted to the outer `let` block. Before this, any runtime error would crash the program with an unhandled rejection.
|
|
145
|
+
|
|
146
|
+
#### Object literals
|
|
147
|
+
|
|
148
|
+
```future
|
|
149
|
+
user = {
|
|
150
|
+
name: "João"
|
|
151
|
+
age: 30
|
|
152
|
+
}
|
|
153
|
+
```
|
|
154
|
+
|
|
155
|
+
No commas between properties — whitespace and newlines act as separators. Optional commas are also accepted for users who prefer them. Emits a standard JS object literal with quoted keys.
|
|
156
|
+
|
|
157
|
+
#### String interpolation
|
|
158
|
+
|
|
159
|
+
```future
|
|
160
|
+
name = "João"
|
|
161
|
+
print "Olá {name}, você tem {user.age} anos"
|
|
162
|
+
```
|
|
163
|
+
|
|
164
|
+
Any string containing `{identifier}` or `{identifier.prop}` is automatically emitted as a JS template literal. No syntax changes required. To emit a literal `{` without interpolation, escape it: `\{`.
|
|
165
|
+
|
|
166
|
+
### New runtime functions
|
|
167
|
+
|
|
168
|
+
#### `system.read(path)` and `system.write(path, content)`
|
|
169
|
+
|
|
170
|
+
```future
|
|
171
|
+
content = system.read("config.json")
|
|
172
|
+
system.write("output.txt", result)
|
|
173
|
+
```
|
|
174
|
+
|
|
175
|
+
`read` returns the file content as a string (UTF-8). `write` creates or overwrites the file, and returns the path that was written.
|
|
176
|
+
|
|
177
|
+
#### `rag.indexFile(path)` and `rag.indexUrl(url)`
|
|
178
|
+
|
|
179
|
+
```future
|
|
180
|
+
rag.indexFile("manual.txt")
|
|
181
|
+
rag.indexUrl("https://docs.example.com/api")
|
|
182
|
+
answer = rag.query("How do I reset the device?")
|
|
183
|
+
```
|
|
184
|
+
|
|
185
|
+
`indexFile` reads a local file and indexes its content into the default knowledge base. `indexUrl` fetches a URL, strips HTML tags, and indexes the resulting text. Both support any text-based format (TXT, MD, JSON, CSV, HTML). For PDFs, convert first: `system.exec("pdftotext manual.pdf manual.txt")`.
|
|
186
|
+
|
|
187
|
+
### Reserved keywords added
|
|
188
|
+
|
|
189
|
+
The following words are now reserved and cannot be used as variable names:
|
|
190
|
+
|
|
191
|
+
- `for`, `in` — iteration
|
|
192
|
+
- `try`, `catch` — error handling
|
|
193
|
+
- `while` — condition-based loop
|
|
194
|
+
- `null`, `none` — null literal
|
|
195
|
+
- `stream` — streaming statement
|
|
196
|
+
- `agent`, `use` — agent declaration
|
|
197
|
+
|
|
198
|
+
No real-world program is expected to be affected — these are common programming keywords.
|
|
199
|
+
|
|
200
|
+
### New language constructs
|
|
201
|
+
|
|
202
|
+
#### `while condition ... end`
|
|
203
|
+
|
|
204
|
+
```future
|
|
205
|
+
count = 0
|
|
206
|
+
while count < 10
|
|
207
|
+
count = count + 1
|
|
208
|
+
end
|
|
209
|
+
```
|
|
210
|
+
|
|
211
|
+
Compiles to `while (cond) { ... }`. Variables assigned inside the body are hoisted to the outer scope.
|
|
212
|
+
|
|
213
|
+
#### `null` and `none` literals
|
|
214
|
+
|
|
215
|
+
```future
|
|
216
|
+
x = null
|
|
217
|
+
if x == none
|
|
218
|
+
print "sem valor"
|
|
219
|
+
end
|
|
220
|
+
```
|
|
221
|
+
|
|
222
|
+
Both `null` and `none` are synonyms — both compile to JS `null`.
|
|
223
|
+
|
|
224
|
+
#### `stream <call> ... end`
|
|
225
|
+
|
|
226
|
+
```future
|
|
227
|
+
stream ai.ask("Conta uma história")
|
|
228
|
+
print chunk
|
|
229
|
+
end
|
|
230
|
+
```
|
|
231
|
+
|
|
232
|
+
Compiles to `await __rt.<namespace>.stream(args, async (chunk) => { ... })`. The body receives an implicit `chunk` variable with each streamed piece of text. Activates ASYNC mode automatically. The call must be a capability call (e.g. `ai.ask`, `ai.chat`).
|
|
233
|
+
|
|
234
|
+
#### `agent <name> ... end`
|
|
235
|
+
|
|
236
|
+
```future
|
|
237
|
+
agent support
|
|
238
|
+
use rag
|
|
239
|
+
use memory
|
|
240
|
+
|
|
241
|
+
docs = rag.query(goal)
|
|
242
|
+
memory.set("last", goal)
|
|
243
|
+
return docs
|
|
244
|
+
end
|
|
245
|
+
|
|
246
|
+
answer = support("Como faço reset?")
|
|
247
|
+
```
|
|
248
|
+
|
|
249
|
+
Compiles to `async function name(goal) { ... }`. The body receives an implicit `goal` parameter — no need to declare it. `use <capability>` lines are documentation only (no generated code). An `agent` declaration always activates ASYNC mode so the call site correctly `await`s the result.
|
|
250
|
+
|
|
251
|
+
### Internal compiler changes
|
|
252
|
+
|
|
253
|
+
- Lexer: tokens LBRACKET (`[`), RBRACKET (`]`), LBRACE (`{`), RBRACE (`}`), COLON (`:`) added.
|
|
254
|
+
- Lexer: `\{` in string literals is stored as `\x01` (placeholder) to prevent generator from treating it as an interpolation start.
|
|
255
|
+
- Parser: `parseFor()`, `parseTry()`, `parseArrayLiteral()`, `parseObjectLiteral()` added.
|
|
256
|
+
- Parser: `EXPR_TERMINATORS` now includes `CATCH` — prevents `return` inside a `try` block from trying to parse `catch` as a value.
|
|
257
|
+
- Generator: `collectAssignedNames` now recurses into `ForStatement.body` and `TryStatement.body/catchBody`. Loop and catch variables are intentionally excluded from hoisting.
|
|
258
|
+
- Generator: `genStringLiteral()` function replaces direct `JSON.stringify` for all string values — handles interpolation detection and `\x01` restoration.
|
|
259
|
+
|
|
260
|
+
---
|
|
261
|
+
|
|
262
|
+
## v0.2.0 → v0.3.0 (Phase 5: AI Stack)
|
|
263
|
+
|
|
264
|
+
**No breaking changes.**
|
|
265
|
+
|
|
266
|
+
### Added — PROMPT_1 (Runtime Foundation)
|
|
267
|
+
|
|
268
|
+
#### New language keywords
|
|
269
|
+
- `on` — event subscription: `on mqtt "topic" ... end`
|
|
270
|
+
- `every` — recurring task: `every "30m" ... end`
|
|
271
|
+
|
|
272
|
+
> These are reserved words. Rename variables named `on` or `every` if any exist.
|
|
273
|
+
|
|
274
|
+
#### New runtime modules
|
|
275
|
+
| Module | Functions |
|
|
276
|
+
|--------|-----------|
|
|
277
|
+
| `memory` | `set`, `get`, `delete`, `search`, `forget` |
|
|
278
|
+
| `schedule` | `every`, `once`, `cron` |
|
|
279
|
+
| `system` | `exec`, `open`, `notify` |
|
|
280
|
+
| `device` | `register`, `get`, `list` |
|
|
281
|
+
|
|
282
|
+
#### Runtime introspection
|
|
283
|
+
- `runtime.listModules()` → all module names
|
|
284
|
+
- `runtime.listFunctions(mod)` → all function names in a module
|
|
285
|
+
- `runtime.describe()` → full manifest + version
|
|
286
|
+
|
|
287
|
+
#### Manifest upgrade
|
|
288
|
+
- Function signatures changed from `'async (prompt)'` strings to structured objects with `description`, `params`, `returns`, `async`.
|
|
289
|
+
- The manifest is consumed by tooling only — not by generated JS. No program is affected.
|
|
290
|
+
|
|
291
|
+
#### New exports
|
|
292
|
+
- `future-lang/runtime/lsp-metadata` — VSCode / LSP metadata module
|
|
293
|
+
|
|
294
|
+
---
|
|
295
|
+
|
|
296
|
+
### Added — PROMPT_2 (AI Stack)
|
|
297
|
+
|
|
298
|
+
#### AI provider abstraction
|
|
299
|
+
- `ai.configure(provider, key, model)` — configure from code
|
|
300
|
+
- `FUTURE_AI_PROVIDER` env var — switch providers without code change
|
|
301
|
+
- Supported: `anthropic`, `openai`, `gemini`, `ollama`, `openrouter`, `venice`, `groq`, `together`
|
|
302
|
+
- Gemini uses Google's OpenAI-compat endpoint — no extra SDK
|
|
303
|
+
|
|
304
|
+
#### New AI functions
|
|
305
|
+
- `ai.embed(text)` → `number[]` — vector embeddings (real or keyword fallback)
|
|
306
|
+
- `ai.stream(prompt, onChunk)` — streaming SSE response
|
|
307
|
+
|
|
308
|
+
#### Real RAG pipeline
|
|
309
|
+
- `rag.index(docs)` now runs a full pipeline: **chunk → embed → vector store → cosine index**
|
|
310
|
+
- `rag.query(question)` now runs: **embed query → similarity search → LLM answer**
|
|
311
|
+
- `rag.create(name)` → named Knowledge Base with isolated vector store
|
|
312
|
+
- `rag.stats()` → chunk and vector count
|
|
313
|
+
- Vector stores: `memory` (default), `file` (JSON persistence), cloud stubs (Qdrant/Pinecone/Weaviate)
|
|
314
|
+
- Offline mode: keyword-based vectors if no embedding API is configured
|
|
315
|
+
|
|
316
|
+
#### Vision upgrade
|
|
317
|
+
- `vision.describe` / `vision.detect` — now use real AI provider (were stubs)
|
|
318
|
+
- `vision.ocr(image)` — new: extract text from image
|
|
319
|
+
- `vision.classify(image)` — new: categorise image
|
|
320
|
+
- `vision.compare(imageA, imageB)` — new: describe differences
|
|
321
|
+
|
|
322
|
+
#### Memory upgrade
|
|
323
|
+
- `memory.forget(pattern?)` — delete by substring pattern or clear all
|
|
324
|
+
|
|
325
|
+
#### Generator fix
|
|
326
|
+
- In async mode, ALL method calls on dynamic objects are now `await`ed.
|
|
327
|
+
- `await` on a synchronous return value is harmless (`await "str"` returns `"str"`).
|
|
328
|
+
- This is required for `kb.query()` and any future runtime-returned objects.
|
|
329
|
+
- Existing programs: no change in behaviour.
|
|
330
|
+
|
|
331
|
+
#### AST additions (architecture only — no parser yet)
|
|
332
|
+
- `AgentDeclaration` — for `agent <name> ... end`
|
|
333
|
+
- `StreamStatement` — for `stream <call> ... end`
|
|
334
|
+
|
|
335
|
+
#### Internal refactoring (no public API change)
|
|
336
|
+
- `runtime/providers/` — provider factory, Anthropic, OpenAI-compat, SSE util
|
|
337
|
+
- `runtime/rag/` — chunker, vector store adapters, pipeline
|
|
338
|
+
|
|
339
|
+
---
|
|
340
|
+
|
|
341
|
+
## Verification
|
|
342
|
+
|
|
343
|
+
After any upgrade, run:
|
|
344
|
+
|
|
345
|
+
```bash
|
|
346
|
+
node --test
|
|
347
|
+
```
|
|
348
|
+
|
|
349
|
+
Expected: **33 tests, 0 failures.**
|
|
350
|
+
|
|
351
|
+
All existing example programs in `examples/` compile and run without modifications.
|
|
352
|
+
|
|
353
|
+
---
|
|
354
|
+
|
|
355
|
+
## Environment variable reference
|
|
356
|
+
|
|
357
|
+
| Variable | Default | Purpose |
|
|
358
|
+
|----------|---------|---------|
|
|
359
|
+
| `FUTURE_AI_PROVIDER` | *(auto)* | `anthropic` \| `openai` \| `gemini` \| `ollama` \| `openrouter` \| `venice` \| `groq` \| `together` |
|
|
360
|
+
| `FUTURE_AI_API_KEY` | — | API key for the selected provider |
|
|
361
|
+
| `FUTURE_AI_BASE_URL` | *(from preset)* | Override base URL for any OpenAI-compat provider |
|
|
362
|
+
| `FUTURE_AI_MODEL` | provider default | Model ID |
|
|
363
|
+
| `ANTHROPIC_API_KEY` | — | Legacy — activates Anthropic without `FUTURE_AI_PROVIDER` |
|
|
364
|
+
| `FUTURE_VECTOR_DB` | `memory` | `memory` \| `file` \| `qdrant` \| `pinecone` \| `weaviate` |
|
|
365
|
+
| `MQTT_URL` | *(loopback)* | MQTT broker URL, e.g. `mqtt://localhost:1883` |
|