steel-lang-2 1.0.0 β†’ 2.0.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
@@ -1,8 +1,8 @@
1
- [![npm](https://img.shields.io/npm/v/steel-lang-2)](https://www.npmjs.com/package/steel-lang-2)
1
+ # Steel Language v2.0
2
2
 
3
- Steel is a simple, readable programming language designed to be easy to learn and intuitive to use.
3
+ [![npm](https://img.shields.io/npm/v/steel-lang-2)](https://www.npmjs.com/package/steel-lang-2)
4
4
 
5
- It focuses on clean syntax, minimal complexity, and fast execution through a custom JavaScript interpreter.
5
+ Steel is a simple, readable programming language designed to be easy to learn and intuitive to use. It focuses on clean syntax, minimal complexity, and fast execution through a custom JavaScript interpreter.
6
6
 
7
7
  ## Install
8
8
 
@@ -10,110 +10,100 @@ It focuses on clean syntax, minimal complexity, and fast execution through a cus
10
10
  npm install steel-lang-2
11
11
  ```
12
12
 
13
+ ## Features
13
14
 
15
+ - **Variables**: `set x to 10`
16
+ - **Output**: `say "Hello!"`
17
+ - **Template Strings**: `` `Hello ${name}!` ``
18
+ - **Conditionals**: `if / elseif / else / end`
19
+ - **Loops**: `while / for / for each / repeat`
20
+ - **Functions**: `define name as (params) ... return value end` with closures and recursion
21
+ - **Arrays**: `[1, 2, 3]` with index access, `set arr[0] to val`
22
+ - **Full Operators**: `+ - * / % > < >= <= == != and or not`
23
+ - **Comments**: `// line comments`
24
+ - **Booleans**: `true`, `false`, `null`
25
+ - **Operator Precedence**: Proper precedence climbing (multiplication before addition, etc.)
14
26
 
27
+ ## Built-in Functions
15
28
 
29
+ ### Math
30
+ `abs`, `round`, `floor`, `ceil`, `sqrt`, `pow`, `min`, `max`, `random`, `pi`, `e`
16
31
 
17
- Features:
18
- β€’ 🧠 Human-readable syntax
19
- β€’ ⚑ Lightweight interpreter (Node.js)
20
- β€’ 🧱 Simple variable system
21
- β€’ πŸ” Control flow (if statements, loops)
22
- β€’ πŸ’¬ Built-in output (say)
23
- β€’ 🎨 VS Code syntax highlighting support
24
- β€’ πŸ”§ Easy to extend and modify
25
-
26
-
27
-
28
-
29
- Project Structure:
30
-
31
- steel-lang/
32
- β”œβ”€β”€ src/ # Language engine
33
- β”‚ β”œβ”€β”€ lexer.js
34
- β”‚ β”œβ”€β”€ parser.js
35
- β”‚ β”œβ”€β”€ interpreter.js
36
- β”‚ β”œβ”€β”€ environment.js
37
- β”‚ └── index.js
38
- β”œβ”€β”€ examples/ # Example programs
39
- β”‚ β”œβ”€β”€ hello.steel
40
- β”‚ β”œβ”€β”€ logic.steel
41
- β”‚ └── variables.steel
42
- β”œβ”€β”€ stl/ # VS Code extension
43
- β”‚ β”œβ”€β”€ syntaxes/
44
- β”‚ β”œβ”€β”€ icons/
45
- β”‚ └── package.json
46
- └── README.md
47
-
48
-
49
-
50
-
51
-
52
- πŸš€ Getting Started
53
-
54
- Clone the repository
55
-
56
- 1. git clone https://github.com/theworker02/steel-lang.git
32
+ ### String
33
+ `len`, `upper`, `lower`, `trim`, `substring`, `replace`, `split`, `join`, `contains`, `charAt`, `indexOf`, `startsWith`, `endsWith`, `repeat`, `padStart`, `padEnd`
57
34
 
58
- 2. cd steel-lang
35
+ ### Array
36
+ `push`, `pop`, `shift`, `unshift`, `reverse`, `sort`, `slice`, `includes`, `flat`, `range`
59
37
 
38
+ ### Type
39
+ `type`, `isNumber`, `isString`, `isArray`, `toString`, `toNumber`
60
40
 
41
+ ### Misc
42
+ `clock`, `sleep`, `input`
61
43
 
62
- Run a Steel program
63
-
64
- 3. "node src/index.js examples/hello.steel"
44
+ ## Quick Start
65
45
 
46
+ ```bash
47
+ git clone https://github.com/magnexis/Steel-lang.git
48
+ cd Steel-lang
49
+ node src/index.js examples/hello.steel
50
+ ```
66
51
 
67
- πŸ§ͺ Example:
52
+ ## Example
68
53
 
69
- set x to 10
54
+ ```steel
55
+ // Variables and types
56
+ set name to "Steel"
57
+ set version to 2
70
58
 
71
- if x > 5 then
72
- say "Steel is working!"
59
+ // Functions with recursion
60
+ define factorial as (n)
61
+ if n <= 1 then
62
+ return 1
63
+ end
64
+ return n * factorial(n - 1)
73
65
  end
74
66
 
67
+ say factorial(10) // 3628800
75
68
 
76
- https://steel-lang.base44.app
77
-
78
-
79
- 🧩 VS Code Extension:
80
-
81
- Steel includes a custom VS Code extension for syntax highlighting.
82
-
83
- Run locally: β€œcd stl”
84
-
85
- Then open the folder in VS code and press: F5
86
-
87
-
88
- 🎯 Goals:
89
-
90
- β€’ Keep syntax simple and readable
91
- β€’ Build a fully custom language ecosystem
92
- β€’ Add functions, modules, and advanced features
93
- β€’ Expand tooling (CLI, debugger, autocomplete)
94
-
95
-
96
- https://steel-lang.base44.app
97
-
98
-
99
- πŸ› οΈ Future Plans:
100
-
101
- β€’ CLI command (steel run file.steel)
102
- β€’ Error handling improvements
103
- β€’ Function system
104
- β€’ Package manager (maybe πŸ‘€)
105
- β€’ Full VS Code integration (IntelliSense)
106
-
107
-
108
- 🀝 Contributing:
69
+ // Arrays and loops
70
+ set nums to [1, 2, 3, 4, 5]
71
+ for each n in nums
72
+ say n * n
73
+ end
109
74
 
110
- Pull requests are welcome. This project is actively evolving and is considered to me still a work in progress. A lot has to be done honestly.
75
+ // Higher-order patterns
76
+ define sum as (arr)
77
+ set total to 0
78
+ for each val in arr
79
+ set total to total + val
80
+ end
81
+ return total
82
+ end
111
83
 
112
- License: MIT License
84
+ say sum(range(1, 101)) // 5050
85
+ ```
113
86
 
114
- Author: theworker02
87
+ ## Project Structure
115
88
 
116
- βš™οΈ Status:
89
+ ```
90
+ steel-lang/
91
+ β”œβ”€β”€ src/ # Language engine
92
+ β”‚ β”œβ”€β”€ lexer.js # Tokenizer
93
+ β”‚ β”œβ”€β”€ parser.js # Recursive descent parser with precedence climbing
94
+ β”‚ β”œβ”€β”€ interpreter.js # Tree-walking interpreter
95
+ β”‚ β”œβ”€β”€ environment.js # Scope, built-ins, function closures
96
+ β”‚ └── index.js # CLI entry point
97
+ β”œβ”€β”€ examples/ # Example programs
98
+ β”‚ β”œβ”€β”€ hello.steel
99
+ β”‚ β”œβ”€β”€ logic.steel
100
+ β”‚ β”œβ”€β”€ variables.steel
101
+ β”‚ β”œβ”€β”€ features-demo.steel
102
+ β”‚ β”œβ”€β”€ control-flow.steel
103
+ β”‚ └── functions-arrays.steel
104
+ └── stl/ # VS Code extension
105
+ ```
117
106
 
118
- 🚧 Early Development/Work in progress, but fully functional
107
+ ## License
119
108
 
109
+ MIT
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "icon": "icons/steel.png",
3
3
  "name": "steel-lang-2",
4
- "version": "1.0.0",
4
+ "version": "2.0.0",
5
5
  "files": [
6
6
  "src/",
7
7
  "icons/"
@@ -1,35 +1,192 @@
1
1
  class Environment {
2
-
3
- constructor() {
4
-
2
+ constructor(parent = null) {
5
3
  this.variables = {};
6
-
4
+ this.parent = parent;
7
5
  }
8
6
 
9
-
10
-
11
7
  set(name, value) {
12
-
13
8
  this.variables[name] = value;
14
-
15
9
  }
16
10
 
17
-
18
-
19
11
  get(name) {
20
-
21
- if (!(name in this.variables)) {
22
-
23
- throw new Error(`Variable "${name}" is not defined`);
24
-
12
+ if (name in this.variables) {
13
+ return this.variables[name];
14
+ }
15
+ if (this.parent) {
16
+ return this.parent.get(name);
25
17
  }
18
+ throw new Error(`Variable "${name}" is not defined`);
19
+ }
26
20
 
27
- return this.variables[name];
21
+ has(name) {
22
+ if (name in this.variables) return true;
23
+ if (this.parent) return this.parent.has(name);
24
+ return false;
25
+ }
28
26
 
27
+ // Function storage
28
+ defineFunction(name, params, body, closureEnv) {
29
+ this.variables[name] = {
30
+ type: 'function',
31
+ params,
32
+ body,
33
+ closure: closureEnv,
34
+ };
29
35
  }
30
36
 
31
- }
37
+ isFunction(name) {
38
+ const val = this.has(name) ? this.get(name) : undefined;
39
+ return val && val.type === 'function';
40
+ }
32
41
 
42
+ callFunction(name, args) {
43
+ const fn = this.get(name);
44
+ if (!fn || fn.type !== 'function') {
45
+ throw new Error(`"${name}" is not a function`);
46
+ }
47
+ const fnEnv = new Environment(fn.closure);
48
+ for (let i = 0; i < fn.params.length; i++) {
49
+ fnEnv.set(fn.params[i], args[i] !== undefined ? args[i] : null);
50
+ }
51
+ return { env: fnEnv, body: fn.body };
52
+ }
33
53
 
54
+ // Built-in functions
55
+ static createGlobal() {
56
+ const env = new Environment();
57
+
58
+ // Math functions
59
+ env.set('abs', { type: 'builtin', fn: Math.abs, name: 'abs' });
60
+ env.set('round', { type: 'builtin', fn: (n) => Math.round(n), name: 'round' });
61
+ env.set('floor', { type: 'builtin', fn: Math.floor, name: 'floor' });
62
+ env.set('ceil', { type: 'builtin', fn: Math.ceil, name: 'ceil' });
63
+ env.set('sqrt', { type: 'builtin', fn: Math.sqrt, name: 'sqrt' });
64
+ env.set('pow', { type: 'builtin', fn: (a, b) => Math.pow(a, b), name: 'pow' });
65
+ env.set('min', { type: 'builtin', fn: Math.min, name: 'min' });
66
+ env.set('max', { type: 'builtin', fn: Math.max, name: 'max' });
67
+ env.set('random', { type: 'builtin', fn: () => Math.random(), name: 'random' });
68
+ env.set('pi', Math.PI);
69
+ env.set('e', Math.E);
70
+
71
+ // String functions
72
+ env.set('len', { type: 'builtin', fn: (v) => {
73
+ if (Array.isArray(v)) return v.length;
74
+ if (typeof v === 'string') return v.length;
75
+ return String(v).length;
76
+ }, name: 'len' });
77
+ env.set('upper', { type: 'builtin', fn: (s) => String(s).toUpperCase(), name: 'upper' });
78
+ env.set('lower', { type: 'builtin', fn: (s) => String(s).toLowerCase(), name: 'lower' });
79
+ env.set('trim', { type: 'builtin', fn: (s) => String(s).trim(), name: 'trim' });
80
+ env.set('substring', { type: 'builtin', fn: (s, start, end) => {
81
+ if (end !== undefined) return String(s).substring(start, end);
82
+ return String(s).substring(start);
83
+ }, name: 'substring' });
84
+ env.set('replace', { type: 'builtin', fn: (s, from, to) => String(s).replaceAll(from, to), name: 'replace' });
85
+ env.set('split', { type: 'builtin', fn: (s, sep) => String(s).split(sep), name: 'split' });
86
+ env.set('join', { type: 'builtin', fn: (arr, sep) => Array.isArray(arr) ? arr.join(sep) : String(arr), name: 'join' });
87
+ env.set('contains', { type: 'builtin', fn: (s, sub) => String(s).includes(sub), name: 'contains' });
88
+ env.set('charAt', { type: 'builtin', fn: (s, i) => String(s).charAt(i), name: 'charAt' });
89
+ env.set('indexOf', { type: 'builtin', fn: (s, sub) => String(s).indexOf(sub), name: 'indexOf' });
90
+ env.set('startsWith', { type: 'builtin', fn: (s, prefix) => String(s).startsWith(prefix), name: 'startsWith' });
91
+ env.set('endsWith', { type: 'builtin', fn: (s, suffix) => String(s).endsWith(suffix), name: 'endsWith' });
92
+ env.set('repeat', { type: 'builtin', fn: (s, n) => String(s).repeat(n), name: 'repeat' });
93
+ env.set('padStart', { type: 'builtin', fn: (s, n, ch) => String(s).padStart(n, ch || ' '), name: 'padStart' });
94
+ env.set('padEnd', { type: 'builtin', fn: (s, n, ch) => String(s).padEnd(n, ch || ' '), name: 'padEnd' });
95
+
96
+ // Type checking
97
+ env.set('type', { type: 'builtin', fn: (v) => {
98
+ if (v === null) return 'null';
99
+ if (Array.isArray(v)) return 'array';
100
+ if (typeof v === 'number') return 'number';
101
+ if (typeof v === 'string') return 'string';
102
+ if (typeof v === 'boolean') return 'boolean';
103
+ return 'unknown';
104
+ }, name: 'type' });
105
+ env.set('isNumber', { type: 'builtin', fn: (v) => typeof v === 'number', name: 'isNumber' });
106
+ env.set('isString', { type: 'builtin', fn: (v) => typeof v === 'string', name: 'isString' });
107
+ env.set('isArray', { type: 'builtin', fn: (v) => Array.isArray(v), name: 'isArray' });
108
+ env.set('toString', { type: 'builtin', fn: (v) => String(v), name: 'toString' });
109
+ env.set('toNumber', { type: 'builtin', fn: (v) => Number(v), name: 'toNumber' });
110
+
111
+ // Array functions
112
+ env.set('push', { type: 'builtin', fn: (arr, item) => {
113
+ if (!Array.isArray(arr)) throw new Error('push() requires an array');
114
+ arr.push(item);
115
+ return arr;
116
+ }, name: 'push' });
117
+ env.set('pop', { type: 'builtin', fn: (arr) => {
118
+ if (!Array.isArray(arr)) throw new Error('pop() requires an array');
119
+ return arr.pop();
120
+ }, name: 'pop' });
121
+ env.set('shift', { type: 'builtin', fn: (arr) => {
122
+ if (!Array.isArray(arr)) throw new Error('shift() requires an array');
123
+ return arr.shift();
124
+ }, name: 'shift' });
125
+ env.set('unshift', { type: 'builtin', fn: (arr, item) => {
126
+ if (!Array.isArray(arr)) throw new Error('unshift() requires an array');
127
+ arr.unshift(item);
128
+ return arr;
129
+ }, name: 'unshift' });
130
+ env.set('reverse', { type: 'builtin', fn: (arr) => {
131
+ if (!Array.isArray(arr)) throw new Error('reverse() requires an array');
132
+ return [...arr].reverse();
133
+ }, name: 'reverse' });
134
+ env.set('sort', { type: 'builtin', fn: (arr) => {
135
+ if (!Array.isArray(arr)) throw new Error('sort() requires an array');
136
+ return [...arr].sort((a, b) => a - b);
137
+ }, name: 'sort' });
138
+ env.set('slice', { type: 'builtin', fn: (arr, start, end) => {
139
+ if (!Array.isArray(arr)) throw new Error('slice() requires an array');
140
+ if (end !== undefined) return arr.slice(start, end);
141
+ return arr.slice(start);
142
+ }, name: 'slice' });
143
+ env.set('indexOf_arr', { type: 'builtin', fn: (arr, item) => {
144
+ if (!Array.isArray(arr)) throw new Error('indexOf requires an array');
145
+ return arr.indexOf(item);
146
+ }, name: 'indexOf_arr' });
147
+ env.set('includes', { type: 'builtin', fn: (arr, item) => {
148
+ if (!Array.isArray(arr)) throw new Error('includes() requires an array');
149
+ return arr.includes(item);
150
+ }, name: 'includes' });
151
+ env.set('flat', { type: 'builtin', fn: (arr, depth) => {
152
+ if (!Array.isArray(arr)) throw new Error('flat() requires an array');
153
+ return arr.flat(depth);
154
+ }, name: 'flat' });
155
+ env.set('range', { type: 'builtin', fn: (start, end, step) => {
156
+ step = step || 1;
157
+ const result = [];
158
+ if (step > 0) {
159
+ for (let i = start; i < end; i += step) result.push(i);
160
+ } else {
161
+ for (let i = start; i > end; i += step) result.push(i);
162
+ }
163
+ return result;
164
+ }, name: 'range' });
165
+
166
+ // I/O
167
+ env.set('input', { type: 'builtin', fn: (prompt) => {
168
+ if (typeof require !== 'undefined') {
169
+ const readline = require('readline');
170
+ const rl = readline.createInterface({ input: process.stdin, output: process.stdout });
171
+ return new Promise((resolve) => {
172
+ rl.question(prompt || '', (answer) => {
173
+ rl.close();
174
+ resolve(answer);
175
+ });
176
+ });
177
+ }
178
+ return null;
179
+ }, name: 'input' });
180
+
181
+ // Misc
182
+ env.set('clock', { type: 'builtin', fn: () => Date.now(), name: 'clock' });
183
+ env.set('sleep', { type: 'builtin', fn: (ms) => {
184
+ const end = Date.now() + ms;
185
+ while (Date.now() < end) {} // busy wait
186
+ }, name: 'sleep' });
187
+
188
+ return env;
189
+ }
190
+ }
34
191
 
35
192
  module.exports = Environment;
package/src/index.js CHANGED
@@ -1,49 +1,43 @@
1
1
  const fs = require('fs');
2
-
3
2
  const { tokenize } = require('./lexer');
4
-
5
3
  const { parse } = require('./parser');
6
-
7
4
  const { interpret } = require('./interpreter');
8
-
9
5
  const Environment = require('./environment');
10
6
 
11
-
12
-
13
7
  const file = process.argv[2];
14
8
 
15
-
16
-
17
9
  if (!file) {
18
-
10
+ console.log("Steel Language Interpreter v2.0.0");
19
11
  console.log("Usage: node src/index.js <file.steel>");
20
-
12
+ console.log("");
13
+ console.log("Features:");
14
+ console.log(" Variables: set x to 10");
15
+ console.log(" Output: say \"Hello!\"");
16
+ console.log(" Conditionals: if x > 5 then ... elseif x > 3 then ... else ... end");
17
+ console.log(" Loops: while x > 0 do ... end");
18
+ console.log(" For loops: for i to 10 ... end | for each item in arr ... end");
19
+ console.log(" Repeat: repeat 5 times ... end");
20
+ console.log(" Functions: define greet as (name) ... return \"Hello \" + name end");
21
+ console.log(" Arrays: set nums to [1, 2, 3, 4, 5]");
22
+ console.log(" Operators: + - * / % > < >= <= == != and or not");
23
+ console.log(" Comments: // this is a comment");
24
+ console.log(" Templates: say `Hello ${name}!`");
25
+ console.log(" Booleans: true, false, null");
26
+ console.log(" Built-ins: abs, round, floor, ceil, sqrt, pow, min, max, random");
27
+ console.log(" Strings: len, upper, lower, trim, substring, replace, split, join");
28
+ console.log(" Arrays: push, pop, shift, unshift, reverse, sort, slice, includes");
29
+ console.log(" Types: type, isNumber, isString, isArray, toString, toNumber");
30
+ console.log(" Misc: pi, e, clock, sleep, input, range");
21
31
  process.exit(1);
22
-
23
32
  }
24
33
 
25
-
26
-
27
34
  try {
28
-
29
35
  const code = fs.readFileSync(file, 'utf-8');
30
-
31
-
32
-
33
36
  const tokens = tokenize(code);
34
-
35
37
  const ast = parse(tokens);
36
-
37
-
38
-
39
- const env = new Environment();
40
-
41
-
42
-
38
+ const env = Environment.createGlobal();
43
39
  interpret(ast, env);
44
-
45
40
  } catch (err) {
46
-
47
- console.error("Error:", err.message);
48
-
41
+ console.error("Error: " + err.message);
42
+ process.exit(1);
49
43
  }