Skip to content

Commit a61cb6c

Browse files
committed
🛠️ ʀᴇꜰᴀᴄᴛᴏʀ — Simplify and replace TokenStream function
2 parents 514da39 + ffaa4c0 commit a61cb6c

File tree

7 files changed

+117
-43
lines changed

7 files changed

+117
-43
lines changed

playground/index.html

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@
4545
<script type="module" src="static/js/panic.js"></script>
4646

4747
<!-- Utilities -->
48-
<script type="module" src="static/js/ast/templates/variable.template.js"></script>
48+
<script type="module" src="static/js/ast/constructors.js"></script>
4949
<script type="module" src="static/js/ast/patterns/functionCall.pattern.js"></script>
5050
<script type="module" src="static/js/ast/patterns/operator.pattern.js"></script>
5151

Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
export function RTValue(content, type) {
2+
this.type = 'Value';
3+
this.content = content;
4+
if (content === undefined)
5+
{
6+
this.type = 'EmptyValue';
7+
this.valType = '?'; // Optional type
8+
}
9+
else this.valType = type ?? inferType(content);
10+
}
11+
12+
export function RTExpression(content) {
13+
this.type = 'Expression';
14+
this.content = content;
15+
}
16+
17+
export function RTVariable(name, value, constant = false) {
18+
this.type = 'Variable';
19+
this.name = name;
20+
this.constant = constant;
21+
this.value = value ?? new RTValue();
22+
23+
// TODO: Add initialization
24+
this.declaration = () => {
25+
let obj = {
26+
...this,
27+
type: 'VariableDeclaration',
28+
varType: this.value.valType
29+
};
30+
delete obj['declaration'];
31+
delete obj['value'];
32+
return obj;
33+
};
34+
}
35+
36+
export function RTAssignment(targetVar, value) {
37+
if (targetVar.constant)
38+
return /*panic(),*/ false;
39+
40+
return {
41+
eval: () => { targetVar.value = value; },
42+
initialization: () => {
43+
let obj = {
44+
targetVar: targetVar.declaration(),
45+
value
46+
}
47+
48+
delete obj['targetVar']['type'];
49+
return obj;
50+
}
51+
};
52+
}
53+
54+
function inferType(value) {
55+
if (!isNaN(value)) {
56+
let possibleTypes = ['uint', 'int'];
57+
const number = parseInt(value);
58+
if (number < 0)
59+
possibleTypes.splice(0, 1); // It's not possible to be unsigned
60+
61+
if (possibleTypes.length === 0)
62+
return false; // TODO: error handling
63+
64+
return possibleTypes[0];
65+
}
66+
67+
if (value.isSurroundedBy('"'))
68+
return 'String';
69+
70+
return 'ID';
71+
}
72+
73+
window.RTValue = RTValue;
74+
window.RTExpression = RTExpression;
75+
window.RTVariable = RTVariable;
76+
window.RTAssignment = RTAssignment;

playground/static/js/ast/parsers/function.parser.js

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ export class ASTFunctionParser {
2828

2929
this.stream.expect('fn');
3030

31-
if (!this.stream.peekTypeEquals("ID"))
31+
if (qrtTypeOf(this.stream.peek()) !== "ID")
3232
return this.stream.error(Errors.AST.Fn_MissingIdentifier);
3333

3434
func.name = this.stream.pop();
@@ -42,11 +42,12 @@ export class ASTFunctionParser {
4242
return this.stream.error(Errors.AST.Fn_MalformedArgs);
4343

4444
while (!this.stream.next(")")) {
45-
if (!this.stream.peekTypeEquals(["TYPE", "ID"]))
45+
if (qrtTypeOf(this.stream.peek()) !== 'TYPE'
46+
&& qrtTypeOf(this.stream.peek()) !== 'ID')
4647
return this.stream.error(Errors.TYPECHECK.Fn_InvalidArgType);
4748

4849
const name = this.stream.pop();
49-
if (!this.stream.peekTypeEquals("ID"))
50+
if (qrtTypeOf(this.stream.peek()) !== 'ID')
5051
return this.stream.error(Errors.AST.Fn_InvalidArgName);
5152

5253
const value = this.stream.pop();
@@ -58,7 +59,9 @@ export class ASTFunctionParser {
5859
}
5960

6061
parseReturnType(func) {
61-
if (this.stream.peekTypeEquals(["ID", "TYPE"])) { // TODO: use RTTypeOf
62+
if (qrtTypeOf(this.stream.peek()) === 'TYPE'
63+
|| qrtTypeOf(this.stream.peek()) === 'ID')
64+
{
6265
func.returnType = this.stream.pop();
6366
return true;
6467
}

playground/static/js/ast/parsers/variable.parser.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ export class ASTVariableParser {
1616
if (!this.stream.expect('let'))
1717
return this.stream.error(Errors.AST.Let_MalformedDeclaration);
1818

19-
if (!this.stream.peekTypeEquals('ID'))
19+
if (qrtTypeOf(this.stream.peek()) !== 'ID')
2020
return this.stream.error(Errors.AST.Let_MissingIdentifier);
2121

2222
variable.name = this.stream.pop();
@@ -25,7 +25,7 @@ export class ASTVariableParser {
2525

2626
// Type declaration
2727
if (this.stream.next(':')) {
28-
if (!this.stream.peekTypeEquals("TYPE"))
28+
if (qrtTypeOf(this.stream.peek()) !== 'TYPE')
2929
return this.stream.error(Errors.TYPECHECK.Let_InvalidType);
3030

3131
variable.varType = this.stream.pop();

playground/static/js/compiler/interpreter.js

Lines changed: 26 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -31,40 +31,40 @@ class Interpreter {
3131
switch (statement.type) {
3232

3333
case 'VariableDeclaration':
34-
if (statement.value) {
35-
let contains = "<RT_UNDEFINED>" /*, valueType*/;
36-
if (statement.value.isSurroundedBy('"')) {
37-
//valueType = 'STR_LITERAL';
38-
contains = statement.value.unwrap();
39-
40-
} else {
41-
//valueType = 'NUM_LITERAL';
42-
contains = parseInt(statement.value);
43-
}
44-
console.log(contains);
45-
this.env.id[statement.name] = contains;
46-
34+
if (!statement.value)
35+
break;
36+
37+
let contains = "<RT_UNDEFINED>" /*, valueType*/;
38+
if (statement.value.isSurroundedBy('"')) {
39+
//valueType = 'STR_LITERAL';
40+
contains = statement.value.unwrap();
41+
} else {
42+
//valueType = 'NUM_LITERAL';
43+
contains = parseInt(statement.value);
4744
}
45+
46+
console.log(contains);
47+
this.env.id[statement.name] = contains;
4848
break;
4949

5050
case 'FunctionDeclaration':
51-
if (statement.name === 'main') {
52-
for (const bodyNode of statement.body) {
53-
this.evaluate(bodyNode);
54-
}
55-
}
56-
break;
51+
if (statement.name !== 'main')
52+
break;
5753

58-
case 'FunctionCall':
59-
if (statement.name === 'println') {
60-
const output = document.getElementById('output');
61-
const value = statement.args[0].isSurroundedBy('"') ?
62-
statement.args[0].unwrap() :
63-
this.env.id[statement.args[0]];
64-
output.innerHTML += value + '\n';
54+
for (const bodyNode of statement.body) {
55+
this.evaluate(bodyNode);
6556
}
6657
break;
6758

59+
case 'FunctionCall':
60+
if (statement.name !== 'println')
61+
break;
62+
63+
const output = document.getElementById('output');
64+
const value = statement.args[0].isSurroundedBy('"') ?
65+
statement.args[0].unwrap() :
66+
this.env.id[statement.args[0]];
67+
output.innerHTML += value + '\n';
6868
}
6969
}
7070

playground/static/js/compiler/util/tokenstream.js

Lines changed: 1 addition & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { detectTokenType } from '../../tokens/types.js'
1+
import { qrtTypeOf } from '../../tokens/types.js'
22
import { CodeStream } from './codestream.js'
33

44
export class TokenStream {
@@ -10,13 +10,6 @@ export class TokenStream {
1010
this.index = 0;
1111
}
1212

13-
peekTypeEquals(type) {
14-
if (!Array.isArray(type))
15-
return detectTokenType(this.peek()) === type;
16-
17-
return type.some(t => this.peekTypeEquals(t));
18-
}
19-
2013
pop() {
2114
return this.tokens[this.index++];
2215
}

playground/static/js/tokens/types.js

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -37,10 +37,10 @@ const types = {
3737

3838
}
3939

40-
export function detectTokenType(s) {
40+
export function qrtTypeOf(s) {
4141
let t = "ID";
4242

43-
if (s[0] === '"')
43+
if (s[0] === '"')
4444
{
4545
t = "STR_LITERAL";
4646
} else if (!(isNaN(parseInt(s)) && isNaN(parseFloat(s)))) {
@@ -58,3 +58,5 @@ export function detectTokenType(s) {
5858
return t;
5959
}
6060

61+
window.qrtTypeOf = qrtTypeOf;
62+

0 commit comments

Comments
 (0)