ga-lang 1.1.0 → 1.2.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.
@@ -1,4 +1,5 @@
1
1
  export class Interpreter {
2
+ environment = new Map();
2
3
  interpret(statements) {
3
4
  for (const statement of statements) {
4
5
  this.execute(statement);
@@ -15,7 +16,8 @@ export class Interpreter {
15
16
  console.log(value);
16
17
  }
17
18
  visitVarStmt(stmt) {
18
- // TODO: yet to implement
19
+ const value = stmt.initializer !== null ? this.evaluate(stmt.initializer) : null;
20
+ this.environment.set(stmt.name.lexeme, value);
19
21
  }
20
22
  visitLiteralExpr(expr) {
21
23
  if (typeof expr.value === 'string' && expr.value.startsWith('"')) {
@@ -24,7 +26,11 @@ export class Interpreter {
24
26
  return expr.value;
25
27
  }
26
28
  visitVariableExpr(expr) {
27
- // TODO: yet to implement
29
+ const value = this.environment.get(expr.name.lexeme);
30
+ if (value === undefined) {
31
+ throw new Error(`Undefined variable '${expr.name.lexeme}'`);
32
+ }
33
+ return value;
28
34
  }
29
35
  /*
30
36
  * Evaluate an expression
package/dist/src/main.js CHANGED
@@ -3,6 +3,9 @@ import { Lexer } from './lexer.js';
3
3
  import { Parser } from './parser.js';
4
4
  import { Interpreter } from './interpreter.js';
5
5
  function getFileNameFromArgs(args) {
6
+ if (args.length <= 0) {
7
+ console.log('> No input files.');
8
+ }
6
9
  if (args.length > 1) {
7
10
  console.log('> Too many arguments.');
8
11
  }
@@ -1,4 +1,4 @@
1
- import { LiteralExpr, PrintStmt, VariableExpr } from './ast.js';
1
+ import { LiteralExpr, PrintStmt, VarStmt, VariableExpr } from './ast.js';
2
2
  import { TokenKind } from './token.js';
3
3
  export class Parser {
4
4
  tokens;
@@ -18,6 +18,9 @@ export class Parser {
18
18
  if (this.match(TokenKind.Print)) {
19
19
  return this.parsePrintStmt();
20
20
  }
21
+ if (this.match(TokenKind.Let)) {
22
+ return this.parseVarStmt();
23
+ }
21
24
  throw this.error(this.peek(), 'Expression expected.');
22
25
  }
23
26
  parsePrintStmt() {
@@ -26,6 +29,14 @@ export class Parser {
26
29
  this.consume(TokenKind.CloseParen, "Expect ')' after expression");
27
30
  return new PrintStmt(expr);
28
31
  }
32
+ parseVarStmt() {
33
+ const name = this.consume(TokenKind.Identifier, "Expect variable name after 'मानौ'");
34
+ let initializer = null;
35
+ if (this.match(TokenKind.Equal)) {
36
+ initializer = this.parseExpression();
37
+ }
38
+ return new VarStmt(name, initializer);
39
+ }
29
40
  parseExpression() {
30
41
  return this.parsePrimary();
31
42
  }
package/examples/init.ga CHANGED
@@ -1,2 +1,4 @@
1
- छाप("सोच्छौ के मेरो बारे?")
2
- छाप(१२३)
1
+ मानौ सन्देश = "सोच्छौ के मेरो बारे?"
2
+ मानौ एकदुइतिन = १२३
3
+ छाप(सन्देश)
4
+ छाप(एकदुइतिन)
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ga-lang",
3
- "version": "1.1.0",
3
+ "version": "1.2.0",
4
4
  "description": "An interpreted toy programming language",
5
5
  "type": "module",
6
6
  "main": "dist/main.js",
@@ -17,7 +17,7 @@
17
17
  },
18
18
  "repository": {
19
19
  "type": "git",
20
- "url": "git+https://github.com/x-incubator/ga.git"
20
+ "url": "git+https://github.com/bvsvntv/ga.git"
21
21
  },
22
22
  "keywords": [
23
23
  "devanagari",
@@ -28,9 +28,9 @@
28
28
  "author": "Basanta Rai",
29
29
  "license": "MIT",
30
30
  "bugs": {
31
- "url": "https://github.com/x-incubator/ga/issues"
31
+ "url": "https://github.com/bvsvntv/ga/issues"
32
32
  },
33
- "homepage": "https://github.com/x-incubator/ga#readme",
33
+ "homepage": "https://github.com/bvsvntv/ga#readme",
34
34
  "packageManager": "pnpm@10.25.0",
35
35
  "engines": {
36
36
  "node": ">=22.x.x",
@@ -10,6 +10,8 @@ import type {
10
10
  } from './ast.js';
11
11
 
12
12
  export class Interpreter implements ExprVisitor<any>, StmtVisitor<void> {
13
+ private environment: Map<string, any> = new Map();
14
+
13
15
  interpret(statements: Stmt[]): void {
14
16
  for (const statement of statements) {
15
17
  this.execute(statement);
@@ -29,7 +31,9 @@ export class Interpreter implements ExprVisitor<any>, StmtVisitor<void> {
29
31
  }
30
32
 
31
33
  visitVarStmt(stmt: VarStmt): void {
32
- // TODO: yet to implement
34
+ const value =
35
+ stmt.initializer !== null ? this.evaluate(stmt.initializer) : null;
36
+ this.environment.set(stmt.name.lexeme, value);
33
37
  }
34
38
 
35
39
  visitLiteralExpr(expr: LiteralExpr): any {
@@ -41,7 +45,11 @@ export class Interpreter implements ExprVisitor<any>, StmtVisitor<void> {
41
45
  }
42
46
 
43
47
  visitVariableExpr(expr: VariableExpr): any {
44
- // TODO: yet to implement
48
+ const value = this.environment.get(expr.name.lexeme);
49
+ if (value === undefined) {
50
+ throw new Error(`Undefined variable '${expr.name.lexeme}'`);
51
+ }
52
+ return value;
45
53
  }
46
54
 
47
55
  /*
package/src/main.ts CHANGED
@@ -4,6 +4,10 @@ import { Parser } from './parser.js';
4
4
  import { Interpreter } from './interpreter.js';
5
5
 
6
6
  function getFileNameFromArgs(args: string[]): string | null {
7
+ if (args.length <= 0) {
8
+ console.log('> No input files.');
9
+ }
10
+
7
11
  if (args.length > 1) {
8
12
  console.log('> Too many arguments.');
9
13
  }
package/src/parser.ts CHANGED
@@ -1,6 +1,7 @@
1
1
  import {
2
2
  LiteralExpr,
3
3
  PrintStmt,
4
+ VarStmt,
4
5
  VariableExpr,
5
6
  type Expr,
6
7
  type Stmt
@@ -30,6 +31,10 @@ export class Parser {
30
31
  return this.parsePrintStmt();
31
32
  }
32
33
 
34
+ if (this.match(TokenKind.Let)) {
35
+ return this.parseVarStmt();
36
+ }
37
+
33
38
  throw this.error(this.peek(), 'Expression expected.');
34
39
  }
35
40
 
@@ -40,6 +45,20 @@ export class Parser {
40
45
  return new PrintStmt(expr);
41
46
  }
42
47
 
48
+ private parseVarStmt(): VarStmt {
49
+ const name = this.consume(
50
+ TokenKind.Identifier,
51
+ "Expect variable name after 'मानौ'"
52
+ );
53
+
54
+ let initializer: Expr | null = null;
55
+ if (this.match(TokenKind.Equal)) {
56
+ initializer = this.parseExpression();
57
+ }
58
+
59
+ return new VarStmt(name, initializer);
60
+ }
61
+
43
62
  private parseExpression(): Expr {
44
63
  return this.parsePrimary();
45
64
  }
@@ -0,0 +1,88 @@
1
+ import test, { describe } from 'node:test';
2
+ import assert from 'node:assert/strict';
3
+ import { Lexer } from '../src/lexer.js';
4
+ import { Parser } from '../src/parser.js';
5
+ import { PrintStmt, VarStmt, LiteralExpr, VariableExpr } from '../src/ast.js';
6
+
7
+ describe('Parser', () => {
8
+ test('parse print statement', () => {
9
+ const source: string = `छाप("नमस्ते")`;
10
+ const lexer: Lexer = new Lexer(source.trim());
11
+ const tokens = lexer.readTokens();
12
+ const parser: Parser = new Parser(tokens);
13
+ const stmts = parser.parse();
14
+
15
+ assert.equal(stmts.length, 1);
16
+ assert.ok(stmts[0] instanceof PrintStmt);
17
+ assert.ok(stmts[0].expression instanceof LiteralExpr);
18
+ });
19
+
20
+ test('parse variable declaration with value', () => {
21
+ const source: string = `मानौ क = १०`;
22
+ const lexer: Lexer = new Lexer(source.trim());
23
+ const tokens = lexer.readTokens();
24
+ const parser: Parser = new Parser(tokens);
25
+ const stmts = parser.parse();
26
+
27
+ assert.equal(stmts.length, 1);
28
+ assert.ok(stmts[0] instanceof VarStmt);
29
+ const varStmt = stmts[0] as VarStmt;
30
+ assert.equal(varStmt.name.lexeme, 'क');
31
+ assert.ok(varStmt.initializer instanceof LiteralExpr);
32
+ });
33
+
34
+ test('parse variable declaration without value', () => {
35
+ const source: string = `मानौ क`;
36
+ const lexer: Lexer = new Lexer(source.trim());
37
+ const tokens = lexer.readTokens();
38
+ const parser: Parser = new Parser(tokens);
39
+ const stmts = parser.parse();
40
+
41
+ assert.equal(stmts.length, 1);
42
+ assert.ok(stmts[0] instanceof VarStmt);
43
+ const varStmt = stmts[0] as VarStmt;
44
+ assert.equal(varStmt.name.lexeme, 'क');
45
+ assert.equal(varStmt.initializer, null);
46
+ });
47
+
48
+ test('parse variable declaration with string', () => {
49
+ const source: string = `मानौ सन्देश = "नमस्ते"`;
50
+ const lexer: Lexer = new Lexer(source.trim());
51
+ const tokens = lexer.readTokens();
52
+ const parser: Parser = new Parser(tokens);
53
+ const stmts = parser.parse();
54
+
55
+ assert.equal(stmts.length, 1);
56
+ assert.ok(stmts[0] instanceof VarStmt);
57
+ const varStmt = stmts[0] as VarStmt;
58
+ assert.equal(varStmt.name.lexeme, 'सन्देश');
59
+ assert.ok(varStmt.initializer instanceof LiteralExpr);
60
+ });
61
+
62
+ test('parse print with variable', () => {
63
+ const source: string = `छाप(सन्देश)`;
64
+ const lexer: Lexer = new Lexer(source.trim());
65
+ const tokens = lexer.readTokens();
66
+ const parser: Parser = new Parser(tokens);
67
+ const stmts = parser.parse();
68
+
69
+ assert.equal(stmts.length, 1);
70
+ assert.ok(stmts[0] instanceof PrintStmt);
71
+ assert.ok(stmts[0].expression instanceof VariableExpr);
72
+ const varExpr = stmts[0].expression as VariableExpr;
73
+ assert.equal(varExpr.name.lexeme, 'सन्देश');
74
+ });
75
+
76
+ test('parse multiple statements', () => {
77
+ const source: string = `मानौ क = १०
78
+ छाप(क)`;
79
+ const lexer: Lexer = new Lexer(source.trim());
80
+ const tokens = lexer.readTokens();
81
+ const parser: Parser = new Parser(tokens);
82
+ const stmts = parser.parse();
83
+
84
+ assert.equal(stmts.length, 2);
85
+ assert.ok(stmts[0] instanceof VarStmt);
86
+ assert.ok(stmts[1] instanceof PrintStmt);
87
+ });
88
+ });