epoxylang 0.1.7 → 0.1.9

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.
@@ -1,8 +1,6 @@
1
1
  assign name = "satya";
2
-
3
- @js{
2
+ @js :~
4
3
  let age = 18;
5
- }
6
-
4
+ ~:
7
5
  store msg = `my name is [name] and i'm [age] years old.`;
8
- show msg;
6
+ show msg;
@@ -1,10 +1,8 @@
1
1
  make square[n] {
2
2
  give n * n;
3
3
  }
4
-
5
4
  assign nums as array = {2, 4, 6};
6
-
7
- repeat[x in 0 to 2, 1]{
5
+ repeat[x in nums]{
8
6
  assign result as int = call square[nums{x}]; $ yaha pe comment dal rhe hai bhaii..
9
7
  store msg = `square of [nums{x}] is [result]`;
10
8
  show msg;
package/examples/test.epx CHANGED
@@ -1,9 +1,10 @@
1
1
  assign numbers as array = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
2
- repeat[i in 0 to 5, 1]{
2
+ repeat[i in numbers]{
3
3
  assign n as int = numbers{i};
4
- @js {
4
+ @js :~
5
5
  if(n % 2 == 0){
6
6
  console.log(n);
7
7
  }
8
- }
9
- }
8
+ ~:
9
+ show "diikhaa..";
10
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "epoxylang",
3
- "version": "0.1.7",
3
+ "version": "0.1.9",
4
4
  "type": "module",
5
5
  "bin": {
6
6
  "epoxy": "./bin/epoxy.js"
@@ -205,13 +205,25 @@ class JSCodeGenerator {
205
205
 
206
206
  visitRepeatFor(node) {
207
207
  const v = node.varName;
208
+ const body = node.body.map(s => this.visit(s)).join("\n");
209
+
210
+ // Handle array iteration: repeat[x in arrayName]
211
+ if (node.arrayName) {
212
+ return `
213
+ for (let ${v} = 0; ${v} < ${node.arrayName}.length; ${v}++) {
214
+ ${body}
215
+ }`.trim();
216
+ }
217
+
218
+ // Handle numeric range with bidirectional support
208
219
  const start = this.visit(node.start);
209
220
  const end = this.visit(node.end);
210
221
  const step = this.visit(node.step);
211
- const body = node.body.map(s => this.visit(s)).join("\n");
212
222
 
223
+ // Generate bidirectional loop: compare start and end at runtime
224
+ // If start <= end: increment, else: decrement
213
225
  return `
214
- for (let ${v} = ${start}; ${v} <= ${end}; ${v} += ${step}) {
226
+ for (let ${v} = ${start}; ${start} <= ${end} ? ${v} <= ${end} : ${v} >= ${end}; ${start} <= ${end} ? ${v} += ${step} : ${v} -= ${step}) {
215
227
  ${body}
216
228
  }`.trim();
217
229
  }
@@ -88,7 +88,7 @@ class Lexer {
88
88
  }
89
89
 
90
90
  readJSBlock() {
91
- // We're at '@', check if next chars are 'js{'
91
+ // We're at '@', check if next chars are 'js~'
92
92
  this.advance(); // skip '@'
93
93
 
94
94
  // Read 'js'
@@ -102,36 +102,32 @@ class Lexer {
102
102
  }
103
103
  this.advance();
104
104
 
105
- // Skip any whitespace before {
105
+ // Skip any whitespace before ~
106
106
  this.skipWhitespace();
107
+ if (this.current !== ':') {
108
+ throw new Error("Expected ':' after '@js'");
109
+ }
110
+ this.advance();
107
111
 
108
- if (this.current !== '{') {
109
- throw new Error("Expected '{' after '@js'");
112
+ if (this.current !== '~') {
113
+ throw new Error("Expected '~' after '@js'");
110
114
  }
111
- this.advance(); // skip '{'
115
+ this.advance(); // skip opening '~'
112
116
 
113
- // Capture everything until matching '}'
117
+ // Capture everything until closing '~'
114
118
  let code = "";
115
- let braceDepth = 1;
116
-
117
- while (this.current && braceDepth > 0) {
118
- if (this.current === '{') {
119
- braceDepth++;
120
- } else if (this.current === '}') {
121
- braceDepth--;
122
- if (braceDepth === 0) {
123
- break; // Don't include the closing brace
124
- }
125
- }
119
+
120
+ while (this.current && this.current !== '~' && this.peek !== ':') {
126
121
  code += this.current;
127
122
  this.advance();
128
123
  }
129
124
 
130
- if (braceDepth !== 0) {
131
- throw new Error("Unmatched braces in @js block");
125
+ if (this.current !== '~' && this.peek !== ':') {
126
+ throw new Error("Unterminated @js block - missing closing '~:'");
132
127
  }
133
128
 
134
- this.advance(); // skip final '}'
129
+ this.advance(); // skip closing '~'
130
+ this.advance(); // skip closing ':'
135
131
 
136
132
  return new Token(TokenType.JSBLOCK, code);
137
133
  }
package/src/parser/ast.js CHANGED
@@ -121,13 +121,14 @@ class ShowStatement {
121
121
  }
122
122
 
123
123
  class RepeatFor {
124
- constructor(varName, start, end, step, body) {
124
+ constructor(varName, start, end, step, body, arrayName = null) {
125
125
  this.type = "RepeatFor";
126
126
  this.varName = varName;
127
127
  this.start = start;
128
128
  this.end = end;
129
129
  this.step = step;
130
130
  this.body = body;
131
+ this.arrayName = arrayName; // For array iteration: repeat[x in arrayName]
131
132
  }
132
133
  }
133
134
 
@@ -542,23 +542,45 @@ class Parser {
542
542
  this.eat(TokenType.IDENTIFIER);
543
543
 
544
544
  this.eat(TokenType.IN);
545
- const start = this.parseExpression();
546
- this.eat(TokenType.TO);
547
- const end = this.parseExpression();
548
545
 
549
- this.eat(TokenType.COMMA);
550
- const step = this.parseExpression();
546
+ // Check if this is array iteration: repeat[x in arrayName]
547
+ // or numeric range: repeat[i in 0 to 5, 1]
548
+ const firstToken = this.current();
551
549
 
552
- this.eat(TokenType.RBRACKET);
553
- this.eat(TokenType.LBRACE);
550
+ if (firstToken.type === TokenType.IDENTIFIER && this.peekType(1) === TokenType.RBRACKET) {
551
+ // Array iteration: repeat[x in arrayName]
552
+ const arrayName = firstToken.value;
553
+ this.eat(TokenType.IDENTIFIER);
554
+ this.eat(TokenType.RBRACKET);
555
+ this.eat(TokenType.LBRACE);
554
556
 
555
- const body = [];
556
- while (this.current().type !== TokenType.RBRACE) {
557
- body.push(this.parseStatement());
558
- }
559
- this.eat(TokenType.RBRACE);
557
+ const body = [];
558
+ while (this.current().type !== TokenType.RBRACE) {
559
+ body.push(this.parseStatement());
560
+ }
561
+ this.eat(TokenType.RBRACE);
562
+
563
+ return new RepeatFor(varName, null, null, null, body, arrayName);
564
+ } else {
565
+ // Numeric range: repeat[i in 0 to 5, 1]
566
+ const start = this.parseExpression();
567
+ this.eat(TokenType.TO);
568
+ const end = this.parseExpression();
569
+
570
+ this.eat(TokenType.COMMA);
571
+ const step = this.parseExpression();
572
+
573
+ this.eat(TokenType.RBRACKET);
574
+ this.eat(TokenType.LBRACE);
560
575
 
561
- return new RepeatFor(varName, start, end, step, body);
576
+ const body = [];
577
+ while (this.current().type !== TokenType.RBRACE) {
578
+ body.push(this.parseStatement());
579
+ }
580
+ this.eat(TokenType.RBRACE);
581
+
582
+ return new RepeatFor(varName, start, end, step, body);
583
+ }
562
584
  }
563
585
 
564
586
  parseShow() {