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
|
@@ -0,0 +1,164 @@
|
|
|
1
|
+
<!DOCTYPE html>
|
|
2
|
+
<html lang="pt">
|
|
3
|
+
<head>
|
|
4
|
+
<meta charset="UTF-8">
|
|
5
|
+
<title>Future — Browser Demo</title>
|
|
6
|
+
<style>
|
|
7
|
+
body { font-family: monospace; max-width: 700px; margin: 2rem auto; padding: 0 1rem; background: #0d1117; color: #e6edf3; }
|
|
8
|
+
h1 { color: #58a6ff; }
|
|
9
|
+
h2 { color: #8b949e; font-size: 0.9rem; font-weight: normal; margin-top: 2rem; }
|
|
10
|
+
pre { background: #161b22; padding: 1rem; border-radius: 6px; border: 1px solid #30363d; overflow-x: auto; }
|
|
11
|
+
#output { background: #0d1117; border: 1px solid #30363d; border-radius: 6px;
|
|
12
|
+
padding: 1rem; min-height: 60px; white-space: pre-wrap; color: #3fb950; }
|
|
13
|
+
.badge { display: inline-block; padding: 2px 8px; border-radius: 4px; font-size: 0.75rem; font-weight: bold; }
|
|
14
|
+
.demo { background: #2d1b00; color: #f0a500; }
|
|
15
|
+
.proxy { background: #0d2b00; color: #3fb950; }
|
|
16
|
+
code { font-family: monospace; }
|
|
17
|
+
</style>
|
|
18
|
+
</head>
|
|
19
|
+
<body>
|
|
20
|
+
|
|
21
|
+
<h1>Future Language — Browser Runtime</h1>
|
|
22
|
+
|
|
23
|
+
<!-- Step 1: load the Future runtime -->
|
|
24
|
+
<script type="module" src="../future-browser.js"></script>
|
|
25
|
+
|
|
26
|
+
<!-- Step 2: configure (runs after future-browser.js, same module tick) -->
|
|
27
|
+
<script type="module">
|
|
28
|
+
import Future from '../future-browser.js';
|
|
29
|
+
|
|
30
|
+
// ── Option A: Proxy mode (production — API key stays on your server) ────────
|
|
31
|
+
// Future.configure({ proxy: '/api/ai' })
|
|
32
|
+
|
|
33
|
+
// ── Option B: Demo mode (dev only — key visible in source) ──────────────────
|
|
34
|
+
// Future.configure({ provider: 'openai', apiKey: 'sk-...' })
|
|
35
|
+
// Future.configure({ provider: 'anthropic', apiKey: 'sk-ant-...' })
|
|
36
|
+
// Future.configure({ provider: 'ollama' }) // local, no key needed
|
|
37
|
+
|
|
38
|
+
// ── Redirect print output to the page ───────────────────────────────────────
|
|
39
|
+
const out = document.getElementById('output');
|
|
40
|
+
Future.runtime.print = (...args) => {
|
|
41
|
+
const line = args.join(' ');
|
|
42
|
+
console.log(line);
|
|
43
|
+
if (out) out.textContent += line + '\n';
|
|
44
|
+
};
|
|
45
|
+
</script>
|
|
46
|
+
|
|
47
|
+
<!-- ─── Example 1: Basic — no AI needed ──────────────────────────────────── -->
|
|
48
|
+
<h2>Example 1 — Basic (no AI required)</h2>
|
|
49
|
+
<pre><code>names = ["Alice", "Bob", "Carlos"]
|
|
50
|
+
for name in names
|
|
51
|
+
print "Olá, {name}!"
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
user = { name: "João" age: 30 }
|
|
55
|
+
if user.age >= 18
|
|
56
|
+
print "{user.name} é adulto"
|
|
57
|
+
end</code></pre>
|
|
58
|
+
|
|
59
|
+
<script type="future">
|
|
60
|
+
names = ["Alice", "Bob", "Carlos"]
|
|
61
|
+
for name in names
|
|
62
|
+
print "Olá, {name}!"
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
user = { name: "João" age: 30 }
|
|
66
|
+
if user.age >= 18
|
|
67
|
+
print "{user.name} é adulto"
|
|
68
|
+
end
|
|
69
|
+
</script>
|
|
70
|
+
|
|
71
|
+
<!-- ─── Example 2: Memory ─────────────────────────────────────────────────── -->
|
|
72
|
+
<h2>Example 2 — Memory (no AI required)</h2>
|
|
73
|
+
<pre><code>memory.set("visits", 1)
|
|
74
|
+
count = memory.get("visits")
|
|
75
|
+
print "Visitas: {count}"</code></pre>
|
|
76
|
+
|
|
77
|
+
<script type="future">
|
|
78
|
+
memory.set("visits", 1)
|
|
79
|
+
count = memory.get("visits")
|
|
80
|
+
print "Visitas: {count}"
|
|
81
|
+
</script>
|
|
82
|
+
|
|
83
|
+
<!-- ─── Example 3: AI ─────────────────────────────────────────────────────── -->
|
|
84
|
+
<h2>Example 3 — AI <span class="badge demo">requires API key or proxy</span></h2>
|
|
85
|
+
<pre><code>try
|
|
86
|
+
answer = ai.ask("What is 2 + 2? Reply with just the number.")
|
|
87
|
+
print "AI diz: {answer}"
|
|
88
|
+
catch err
|
|
89
|
+
print "AI não configurada — adiciona uma key ou proxy"
|
|
90
|
+
end</code></pre>
|
|
91
|
+
|
|
92
|
+
<script type="future">
|
|
93
|
+
try
|
|
94
|
+
answer = ai.ask("What is 2 + 2? Reply with just the number.")
|
|
95
|
+
print "AI diz: {answer}"
|
|
96
|
+
catch err
|
|
97
|
+
print "AI não configurada — adiciona uma key ou proxy"
|
|
98
|
+
end
|
|
99
|
+
</script>
|
|
100
|
+
|
|
101
|
+
<!-- ─── Example 4: Agent ──────────────────────────────────────────────────── -->
|
|
102
|
+
<h2>Example 4 — Agent <span class="badge demo">requires API key or proxy</span></h2>
|
|
103
|
+
<pre><code>agent tradutor
|
|
104
|
+
use ai
|
|
105
|
+
resultado = ai.ask("Traduz para português: {goal}")
|
|
106
|
+
return resultado
|
|
107
|
+
end
|
|
108
|
+
|
|
109
|
+
try
|
|
110
|
+
pt = tradutor("Good morning, how are you?")
|
|
111
|
+
print pt
|
|
112
|
+
catch err
|
|
113
|
+
print "Agent precisa de AI — adiciona uma key ou proxy"
|
|
114
|
+
end</code></pre>
|
|
115
|
+
|
|
116
|
+
<script type="future">
|
|
117
|
+
agent tradutor
|
|
118
|
+
use ai
|
|
119
|
+
resultado = ai.ask("Traduz para português: {goal}")
|
|
120
|
+
return resultado
|
|
121
|
+
end
|
|
122
|
+
|
|
123
|
+
try
|
|
124
|
+
pt = tradutor("Good morning, how are you?")
|
|
125
|
+
print pt
|
|
126
|
+
catch err
|
|
127
|
+
print "Agent precisa de AI — adiciona uma key ou proxy"
|
|
128
|
+
end
|
|
129
|
+
</script>
|
|
130
|
+
|
|
131
|
+
<!-- ─── Output ────────────────────────────────────────────────────────────── -->
|
|
132
|
+
<h2>Output</h2>
|
|
133
|
+
<div id="output"></div>
|
|
134
|
+
|
|
135
|
+
<!-- ─── Proxy server example ──────────────────────────────────────────────── -->
|
|
136
|
+
<h2>Proxy server example <span class="badge proxy">production</span></h2>
|
|
137
|
+
<pre><code>// server.js — guarda a tua key no servidor, nunca no browser
|
|
138
|
+
import express from 'express'
|
|
139
|
+
import { runtime } from 'future-lang/runtime'
|
|
140
|
+
|
|
141
|
+
const app = express()
|
|
142
|
+
app.use(express.json())
|
|
143
|
+
|
|
144
|
+
runtime.ai.configure('openai', process.env.OPENAI_KEY)
|
|
145
|
+
|
|
146
|
+
app.post('/api/ai/ask', async (req, res) => res.json({ text: await runtime.ai.ask(req.body.prompt) }))
|
|
147
|
+
app.post('/api/ai/chat', async (req, res) => res.json({ text: await runtime.ai.chat(req.body.messages) }))
|
|
148
|
+
app.post('/api/ai/embed', async (req, res) => res.json({ embedding: await runtime.ai.embed(req.body.text) }))
|
|
149
|
+
app.listen(3000)</code></pre>
|
|
150
|
+
|
|
151
|
+
<pre><code><!-- HTML — a key nunca aparece aqui -->
|
|
152
|
+
<script type="module" src="future-browser.js"></script>
|
|
153
|
+
<script type="module">
|
|
154
|
+
import Future from './future-browser.js'
|
|
155
|
+
Future.configure({ proxy: '/api/ai' })
|
|
156
|
+
</script>
|
|
157
|
+
|
|
158
|
+
<script type="future">
|
|
159
|
+
answer = ai.ask("Olá!")
|
|
160
|
+
print answer
|
|
161
|
+
</script></code></pre>
|
|
162
|
+
|
|
163
|
+
</body>
|
|
164
|
+
</html>
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
print "Hello World"
|
|
@@ -0,0 +1,301 @@
|
|
|
1
|
+
<!DOCTYPE html>
|
|
2
|
+
<html lang="en">
|
|
3
|
+
<head>
|
|
4
|
+
<meta charset="utf-8" />
|
|
5
|
+
<title>Future — mini app test</title>
|
|
6
|
+
</head>
|
|
7
|
+
<body>
|
|
8
|
+
|
|
9
|
+
<h1>Future runtime test</h1>
|
|
10
|
+
<pre id="out" style="background:#111;color:#0f0;padding:1rem;min-height:200px;white-space:pre-wrap"></pre>
|
|
11
|
+
|
|
12
|
+
<!-- ── 1. Load the runtime ──────────────────────────────────────────────────── -->
|
|
13
|
+
<script type="module" src="../future-browser.js"></script>
|
|
14
|
+
|
|
15
|
+
<!-- ── 2. Configure: redirect print + set AI key ────────────────────────────── -->
|
|
16
|
+
<script type="module">
|
|
17
|
+
import Future from '../future-browser.js';
|
|
18
|
+
|
|
19
|
+
const out = document.getElementById('out');
|
|
20
|
+
Future.runtime.print = (...args) => {
|
|
21
|
+
out.textContent += args.join(' ') + '\n';
|
|
22
|
+
};
|
|
23
|
+
|
|
24
|
+
// Uncomment to test AI (programs 10 and 11):
|
|
25
|
+
// Future.configure({ proxy: '/api/ai' });
|
|
26
|
+
// Future.configure({ provider: 'venice', apiKey: 'your-key-here' });
|
|
27
|
+
//
|
|
28
|
+
// Or set window.__env before this script and use system.env() from Future code:
|
|
29
|
+
window.__env = { VENICE_API_KEY: 'VENICE-INFERENCE-KEY-n9mnNP2DsEdj-M8osOKWgwpxou51VXtWlAlpasmdnl' }
|
|
30
|
+
</script>
|
|
31
|
+
|
|
32
|
+
<!-- ── Future programs ────────────────────────────────────────────────────────
|
|
33
|
+
Tip: string interpolation supports {variable} and {object.prop} only.
|
|
34
|
+
Function calls must be assigned to a variable first:
|
|
35
|
+
n = len(items)
|
|
36
|
+
print "Count: {n}" ✓
|
|
37
|
+
print "Count: {len(items)}" ✗ (stays as literal text)
|
|
38
|
+
──────────────────────────────────────────────────────────────────────────── -->
|
|
39
|
+
|
|
40
|
+
<!-- Program 1: variables, strings, lists, for -->
|
|
41
|
+
<script type="future">
|
|
42
|
+
print "=== 1. Basic ==="
|
|
43
|
+
name = "Future"
|
|
44
|
+
version = 0.3
|
|
45
|
+
print "Language: {name} v{version}"
|
|
46
|
+
|
|
47
|
+
items = ["alpha", "beta", "gamma", "delta"]
|
|
48
|
+
n = len(items)
|
|
49
|
+
print "List has {n} items:"
|
|
50
|
+
for item in items
|
|
51
|
+
print " - {item}"
|
|
52
|
+
end
|
|
53
|
+
</script>
|
|
54
|
+
|
|
55
|
+
<!-- Program 2: math module -->
|
|
56
|
+
<script type="future">
|
|
57
|
+
print "=== 2. Math ==="
|
|
58
|
+
a = math.round(3.7)
|
|
59
|
+
b = math.floor(3.9)
|
|
60
|
+
c = math.ceil(3.1)
|
|
61
|
+
d = math.abs(-42)
|
|
62
|
+
e = math.sqrt(144)
|
|
63
|
+
f = math.pow(2, 10)
|
|
64
|
+
g = math.max(3, 9, 1, 7)
|
|
65
|
+
h = math.min(3, 9, 1, 7)
|
|
66
|
+
r = math.random()
|
|
67
|
+
print "round(3.7) = {a}"
|
|
68
|
+
print "floor(3.9) = {b}"
|
|
69
|
+
print "ceil(3.1) = {c}"
|
|
70
|
+
print "abs(-42) = {d}"
|
|
71
|
+
print "sqrt(144) = {e}"
|
|
72
|
+
print "pow(2,10) = {f}"
|
|
73
|
+
print "max(3,9,1,7) = {g}"
|
|
74
|
+
print "min(3,9,1,7) = {h}"
|
|
75
|
+
print "random() = {r}"
|
|
76
|
+
print "pi = {math.pi}"
|
|
77
|
+
print "e = {math.e}"
|
|
78
|
+
</script>
|
|
79
|
+
|
|
80
|
+
<!-- Program 3: while loop + len — use for to sum (no bracket index in Future) -->
|
|
81
|
+
<script type="future">
|
|
82
|
+
print "=== 3. While + for accumulator ==="
|
|
83
|
+
scores = [72, 85, 91, 60, 88, 95, 78]
|
|
84
|
+
n = len(scores)
|
|
85
|
+
|
|
86
|
+
# sum with for (Future has no array[i] index access yet)
|
|
87
|
+
total = 0
|
|
88
|
+
for s in scores
|
|
89
|
+
total = total + s
|
|
90
|
+
end
|
|
91
|
+
|
|
92
|
+
avg = math.round(total / n)
|
|
93
|
+
best = math.max(72, 85, 91, 60, 88, 95, 78)
|
|
94
|
+
worst = math.min(72, 85, 91, 60, 88, 95, 78)
|
|
95
|
+
print "Count: {n} Total: {total} Avg: {avg}"
|
|
96
|
+
print "Best: {best} Worst: {worst}"
|
|
97
|
+
|
|
98
|
+
# while loop counting down
|
|
99
|
+
i = 5
|
|
100
|
+
print "Countdown:"
|
|
101
|
+
while i > 0
|
|
102
|
+
print " {i}"
|
|
103
|
+
i = i - 1
|
|
104
|
+
end
|
|
105
|
+
print " go!"
|
|
106
|
+
</script>
|
|
107
|
+
|
|
108
|
+
<!-- Program 4: objects, null, conditionals -->
|
|
109
|
+
<script type="future">
|
|
110
|
+
print "=== 4. Objects + null ==="
|
|
111
|
+
user = { name: "Alice" age: 28 role: "admin" }
|
|
112
|
+
print "Name: {user.name} Age: {user.age} Role: {user.role}"
|
|
113
|
+
|
|
114
|
+
session = null
|
|
115
|
+
if session == null
|
|
116
|
+
print "No active session"
|
|
117
|
+
else
|
|
118
|
+
print "Session active"
|
|
119
|
+
end
|
|
120
|
+
|
|
121
|
+
if user.age >= 18
|
|
122
|
+
print "{user.name} is an adult"
|
|
123
|
+
end
|
|
124
|
+
|
|
125
|
+
# nested object access
|
|
126
|
+
product = { name: "Widget" price: 9.99 }
|
|
127
|
+
total = product.price * 3
|
|
128
|
+
rounded = math.round(total * 100) / 100
|
|
129
|
+
print "3x {product.name} = {rounded}"
|
|
130
|
+
</script>
|
|
131
|
+
|
|
132
|
+
<!-- Program 5: functions -->
|
|
133
|
+
<script type="future">
|
|
134
|
+
print "=== 5. Functions ==="
|
|
135
|
+
|
|
136
|
+
function greet(name)
|
|
137
|
+
return "Hello, {name}!"
|
|
138
|
+
end
|
|
139
|
+
|
|
140
|
+
function factorial(n)
|
|
141
|
+
if n <= 1
|
|
142
|
+
return 1
|
|
143
|
+
end
|
|
144
|
+
return n * factorial(n - 1)
|
|
145
|
+
end
|
|
146
|
+
|
|
147
|
+
function clamp(value, lo, hi)
|
|
148
|
+
if value < lo
|
|
149
|
+
return lo
|
|
150
|
+
end
|
|
151
|
+
if value > hi
|
|
152
|
+
return hi
|
|
153
|
+
end
|
|
154
|
+
return value
|
|
155
|
+
end
|
|
156
|
+
|
|
157
|
+
msg = greet("World")
|
|
158
|
+
print msg
|
|
159
|
+
|
|
160
|
+
f5 = factorial(5)
|
|
161
|
+
f10 = factorial(10)
|
|
162
|
+
print "5! = {f5}"
|
|
163
|
+
print "10! = {f10}"
|
|
164
|
+
|
|
165
|
+
c1 = clamp(150, 0, 100)
|
|
166
|
+
c2 = clamp(-10, 0, 100)
|
|
167
|
+
c3 = clamp(42, 0, 100)
|
|
168
|
+
print "clamp(150, 0, 100) = {c1}"
|
|
169
|
+
print "clamp(-10, 0, 100) = {c2}"
|
|
170
|
+
print "clamp(42, 0, 100) = {c3}"
|
|
171
|
+
</script>
|
|
172
|
+
|
|
173
|
+
<!-- Program 6: memory module -->
|
|
174
|
+
<script type="future">
|
|
175
|
+
print "=== 6. Memory ==="
|
|
176
|
+
memory.set("app", "FutureTest")
|
|
177
|
+
memory.set("version", "0.3.2")
|
|
178
|
+
memory.set("user", "Alice")
|
|
179
|
+
memory.set("score", 99)
|
|
180
|
+
|
|
181
|
+
app = memory.get("app")
|
|
182
|
+
ver = memory.get("version")
|
|
183
|
+
print "Running {app} v{ver}"
|
|
184
|
+
|
|
185
|
+
results = memory.search("ver")
|
|
186
|
+
n = len(results)
|
|
187
|
+
print "Keys matching 'ver': {n}"
|
|
188
|
+
|
|
189
|
+
memory.forget("user")
|
|
190
|
+
gone = memory.get("user")
|
|
191
|
+
if gone == null
|
|
192
|
+
print "user key deleted"
|
|
193
|
+
end
|
|
194
|
+
|
|
195
|
+
score = memory.get("score")
|
|
196
|
+
print "score = {score}"
|
|
197
|
+
</script>
|
|
198
|
+
|
|
199
|
+
<!-- Program 7: try / catch + custom error-safe function -->
|
|
200
|
+
<script type="future">
|
|
201
|
+
print "=== 7. Error handling ==="
|
|
202
|
+
|
|
203
|
+
function safeDivide(a, b)
|
|
204
|
+
if b == 0
|
|
205
|
+
return null
|
|
206
|
+
end
|
|
207
|
+
return a / b
|
|
208
|
+
end
|
|
209
|
+
|
|
210
|
+
r1 = safeDivide(10, 2)
|
|
211
|
+
r2 = safeDivide(10, 0)
|
|
212
|
+
print "10 / 2 = {r1}"
|
|
213
|
+
print "10 / 0 = {r2}"
|
|
214
|
+
|
|
215
|
+
try
|
|
216
|
+
bad = http.get("https://this-does-not-exist-xyz123.com/api")
|
|
217
|
+
print bad
|
|
218
|
+
catch err
|
|
219
|
+
print "Caught expected error: request failed"
|
|
220
|
+
end
|
|
221
|
+
|
|
222
|
+
print "Execution continues after catch"
|
|
223
|
+
</script>
|
|
224
|
+
|
|
225
|
+
<!-- Program 8: HTTP (live fetch) -->
|
|
226
|
+
<script type="future">
|
|
227
|
+
print "=== 8. HTTP ==="
|
|
228
|
+
todo = http.get("https://jsonplaceholder.typicode.com/todos/3")
|
|
229
|
+
print "Title: {todo.title}"
|
|
230
|
+
print "Completed: {todo.completed}"
|
|
231
|
+
|
|
232
|
+
user = http.get("https://jsonplaceholder.typicode.com/users/1")
|
|
233
|
+
print "User: {user.name}"
|
|
234
|
+
print "Email: {user.email}"
|
|
235
|
+
print "City: {user.address.city}"
|
|
236
|
+
</script>
|
|
237
|
+
|
|
238
|
+
<!-- Program 9: system.env -->
|
|
239
|
+
<script type="future">
|
|
240
|
+
print "=== 9. system.env ==="
|
|
241
|
+
# In the browser, reads from window.__env
|
|
242
|
+
# In Node.js CLI, reads from process.env
|
|
243
|
+
key = system.env("VENICE_API_KEY")
|
|
244
|
+
if key == null
|
|
245
|
+
print "VENICE_API_KEY not set"
|
|
246
|
+
print "Set window.__env = { VENICE_API_KEY: '...' } before loading the page"
|
|
247
|
+
else
|
|
248
|
+
n = len(key)
|
|
249
|
+
print "VENICE_API_KEY is set ({n} chars)"
|
|
250
|
+
end
|
|
251
|
+
</script>
|
|
252
|
+
|
|
253
|
+
<!-- Program 10: agent (no AI call — works without any key) -->
|
|
254
|
+
<script type="future">
|
|
255
|
+
print "=== 10. Agent (no AI) ==="
|
|
256
|
+
|
|
257
|
+
agent greet
|
|
258
|
+
msg = "Hello from agent! Goal: {goal}"
|
|
259
|
+
return msg
|
|
260
|
+
end
|
|
261
|
+
|
|
262
|
+
agent measure
|
|
263
|
+
n = len(goal)
|
|
264
|
+
return "Input has {n} characters"
|
|
265
|
+
end
|
|
266
|
+
|
|
267
|
+
agent double
|
|
268
|
+
result = goal + " | " + goal
|
|
269
|
+
return result
|
|
270
|
+
end
|
|
271
|
+
|
|
272
|
+
r1 = greet("test the runtime")
|
|
273
|
+
r2 = measure("Hello Future language!")
|
|
274
|
+
r3 = double("ping")
|
|
275
|
+
print r1
|
|
276
|
+
print r2
|
|
277
|
+
print r3
|
|
278
|
+
</script>
|
|
279
|
+
|
|
280
|
+
<!-- Program 11: AI (requires key or proxy — skips cleanly if not set) -->
|
|
281
|
+
<script type="future">
|
|
282
|
+
print "=== 11. AI ==="
|
|
283
|
+
|
|
284
|
+
# To enable: configure in the <script type="module"> block above
|
|
285
|
+
key = system.env("VENICE_API_KEY")
|
|
286
|
+
if key == null
|
|
287
|
+
print "AI skipped — no key configured"
|
|
288
|
+
print "Set window.__env.VENICE_API_KEY or Future.configure({ proxy: '/api/ai' })"
|
|
289
|
+
else
|
|
290
|
+
ai.configure("venice", key)
|
|
291
|
+
try
|
|
292
|
+
answer = ai.ask("Reply with exactly three words: Future is awesome")
|
|
293
|
+
print "AI says: {answer}"
|
|
294
|
+
catch err
|
|
295
|
+
print "AI error: {err}"
|
|
296
|
+
end
|
|
297
|
+
end
|
|
298
|
+
</script>
|
|
299
|
+
|
|
300
|
+
</body>
|
|
301
|
+
</html>
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
# Automação residencial sobre MQTT (loopback local, roda sem broker)
|
|
2
|
+
function aoReceber(mensagem)
|
|
3
|
+
print "Sensor disse: " + mensagem
|
|
4
|
+
end
|
|
5
|
+
|
|
6
|
+
mqtt.subscribe("casa/sala/temperatura", aoReceber)
|
|
7
|
+
mqtt.publish("casa/sala/temperatura", "23.5")
|
|
8
|
+
|
|
9
|
+
home.turnOn("luz_sala")
|
|
10
|
+
print "Luz da sala ligada."
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
// future-browser.js — Browser runtime for the Future programming language.
|
|
2
|
+
//
|
|
3
|
+
// Usage:
|
|
4
|
+
// <script type="module" src="future-browser.js"></script>
|
|
5
|
+
//
|
|
6
|
+
// <!-- Option A: Proxy mode (production — key stays on your server) -->
|
|
7
|
+
// <script>Future.configure({ proxy: '/api/ai' })</script>
|
|
8
|
+
//
|
|
9
|
+
// <!-- Option B: Demo mode (key visible in HTML — dev/demos only) -->
|
|
10
|
+
// <script>Future.configure({ provider: 'openai', apiKey: 'sk-...' })</script>
|
|
11
|
+
//
|
|
12
|
+
// <!-- Then write Future code anywhere on the page -->
|
|
13
|
+
// <script type="future">
|
|
14
|
+
// answer = ai.ask("Olá mundo")
|
|
15
|
+
// print answer
|
|
16
|
+
// </script>
|
|
17
|
+
//
|
|
18
|
+
// Proxy contract (for Option A):
|
|
19
|
+
// POST {proxy}/ask { prompt } → { text }
|
|
20
|
+
// POST {proxy}/chat { messages } → { text }
|
|
21
|
+
// POST {proxy}/stream { prompt } → SSE (OpenAI format)
|
|
22
|
+
// POST {proxy}/embed { text } → { embedding: number[] }
|
|
23
|
+
|
|
24
|
+
import { tokenize } from './src/lexer.js';
|
|
25
|
+
import { parse } from './src/parser.js';
|
|
26
|
+
import { generate } from './src/generator.js';
|
|
27
|
+
import { browserRuntime, setProxy, ai } from './runtime/browser.js';
|
|
28
|
+
|
|
29
|
+
// ─── Public API ───────────────────────────────────────────────────────────────
|
|
30
|
+
|
|
31
|
+
const Future = {
|
|
32
|
+
/**
|
|
33
|
+
* Configure the browser runtime.
|
|
34
|
+
*
|
|
35
|
+
* Proxy mode (production):
|
|
36
|
+
* Future.configure({ proxy: '/api/ai' })
|
|
37
|
+
*
|
|
38
|
+
* Demo mode (development):
|
|
39
|
+
* Future.configure({ provider: 'openai', apiKey: 'sk-...' })
|
|
40
|
+
* Future.configure({ provider: 'anthropic', apiKey: 'sk-ant-...' })
|
|
41
|
+
* Future.configure({ provider: 'ollama' }) // local, no key needed
|
|
42
|
+
*/
|
|
43
|
+
configure(options = {}) {
|
|
44
|
+
if (options.proxy) {
|
|
45
|
+
setProxy(options.proxy);
|
|
46
|
+
}
|
|
47
|
+
if (options.provider || options.apiKey) {
|
|
48
|
+
ai.configure(options.provider ?? 'openai', options.apiKey ?? null, options.model ?? null);
|
|
49
|
+
}
|
|
50
|
+
},
|
|
51
|
+
|
|
52
|
+
/**
|
|
53
|
+
* Compile and run a Future source string.
|
|
54
|
+
* Returns a Promise that resolves when the program finishes.
|
|
55
|
+
*/
|
|
56
|
+
async run(source) {
|
|
57
|
+
let js;
|
|
58
|
+
try {
|
|
59
|
+
js = generate(parse(tokenize(String(source))), { browserMode: true });
|
|
60
|
+
} catch (e) {
|
|
61
|
+
console.error('[Future] Compile error:', e.message);
|
|
62
|
+
throw e;
|
|
63
|
+
}
|
|
64
|
+
// Wrap in async IIFE; __rt is passed as parameter (not a global).
|
|
65
|
+
// __rt is always passed — even in SIMPLE mode — so __rt.print is available.
|
|
66
|
+
const fn = new Function('__rt', `return (async () => {\n${js}\n})()`);
|
|
67
|
+
return fn(browserRuntime);
|
|
68
|
+
},
|
|
69
|
+
|
|
70
|
+
/** Compile Future source to JavaScript without running it. */
|
|
71
|
+
compile(source) {
|
|
72
|
+
return generate(parse(tokenize(String(source))), { browserMode: true });
|
|
73
|
+
},
|
|
74
|
+
|
|
75
|
+
/** The underlying runtime object — useful for REPL or direct capability calls. */
|
|
76
|
+
runtime: browserRuntime,
|
|
77
|
+
};
|
|
78
|
+
|
|
79
|
+
// ─── <script type="future"> interceptor ──────────────────────────────────────
|
|
80
|
+
|
|
81
|
+
async function runScripts() {
|
|
82
|
+
const scripts = document.querySelectorAll('script[type="future"]');
|
|
83
|
+
for (const script of scripts) {
|
|
84
|
+
const source = script.textContent ?? '';
|
|
85
|
+
if (!source.trim()) continue;
|
|
86
|
+
try {
|
|
87
|
+
await Future.run(source);
|
|
88
|
+
} catch (e) {
|
|
89
|
+
console.error(`[Future] Runtime error in <script type="future">:`, e);
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
// Defer runScripts with setTimeout so all <script type="module"> blocks on the
|
|
95
|
+
// page (including configuration scripts that set proxy or override print) finish
|
|
96
|
+
// initialising before any <script type="future"> block runs.
|
|
97
|
+
setTimeout(runScripts, 0);
|
|
98
|
+
|
|
99
|
+
// ─── Expose globally ──────────────────────────────────────────────────────────
|
|
100
|
+
|
|
101
|
+
window.Future = Future;
|
|
102
|
+
export default Future;
|