mirror of
https://github.com/bendtherules/not-a-js-engine.git
synced 2026-08-18 22:01:53 +00:00
Feature - Support plus binary expression for number and string
This commit is contained in:
@@ -6,6 +6,7 @@ import {
|
||||
NumericLiteral,
|
||||
StringLiteral,
|
||||
Program,
|
||||
BinaryExpression,
|
||||
} from './types';
|
||||
|
||||
export function isProgram(node: Node): node is Program {
|
||||
@@ -27,3 +28,7 @@ export function isNumericLiteral(node: Node): node is NumericLiteral {
|
||||
export function isStringLiteral(node: Node): node is StringLiteral {
|
||||
return isLiteral(node) && typeof node.value === 'string';
|
||||
}
|
||||
|
||||
export function isBinaryExpression(node: Node): node is BinaryExpression {
|
||||
return node.type === TypeStrings.BinaryExpression;
|
||||
}
|
||||
|
||||
@@ -6,6 +6,7 @@ export enum TypeStrings {
|
||||
Program = 'Program',
|
||||
ExpressionStatement = 'ExpressionStatement',
|
||||
Literal = 'Literal',
|
||||
BinaryExpression = 'BinaryExpression',
|
||||
}
|
||||
|
||||
export interface Program extends Node {
|
||||
@@ -18,7 +19,8 @@ export interface ExpressionStatement extends Node {
|
||||
expression: Expression;
|
||||
}
|
||||
|
||||
export type Expression = Literal | Node;
|
||||
// TODO: Add more possible type of expressions here and remove generic node
|
||||
export type Expression = Literal | BinaryExpression | Node;
|
||||
|
||||
export interface Literal extends Node {
|
||||
type: TypeStrings.Literal;
|
||||
@@ -34,3 +36,11 @@ export interface StringLiteral extends Node {
|
||||
type: TypeStrings.Literal;
|
||||
value: string;
|
||||
}
|
||||
|
||||
export interface BinaryExpression extends Node {
|
||||
type: TypeStrings.BinaryExpression;
|
||||
left: Literal;
|
||||
right: Literal;
|
||||
// TODO: Add actual possible operators here
|
||||
operator: string;
|
||||
}
|
||||
|
||||
@@ -4,11 +4,13 @@ import {
|
||||
isNumericLiteral,
|
||||
isStringLiteral,
|
||||
isProgram,
|
||||
isBinaryExpression,
|
||||
} from './acorn-helpers/isType';
|
||||
|
||||
import {
|
||||
NormalCompletion,
|
||||
CompletionRecord,
|
||||
v,
|
||||
} from './internal-types/CompletionRecord';
|
||||
|
||||
import { NumberValue } from './language-types/NumberValue';
|
||||
@@ -30,6 +32,22 @@ export function Evaluate(node: Node): CompletionRecord {
|
||||
} else if (isStringLiteral(node)) {
|
||||
// Handle StringLiteral
|
||||
return NormalCompletion(new StringValue(node.value));
|
||||
} else if (isBinaryExpression(node)) {
|
||||
if (node.operator === '+') {
|
||||
// TODO - Forward completion record for abrupt completions
|
||||
const leftVal = v(Evaluate(node.left));
|
||||
const rightVal = v(Evaluate(node.right));
|
||||
if (leftVal instanceof NumberValue && rightVal instanceof NumberValue) {
|
||||
return NormalCompletion(
|
||||
new NumberValue(leftVal.getValue() + rightVal.getValue())
|
||||
);
|
||||
}
|
||||
if (leftVal instanceof StringValue && rightVal instanceof StringValue) {
|
||||
return NormalCompletion(
|
||||
new StringValue(leftVal.getValue() + rightVal.getValue())
|
||||
);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// If not handled, throw error
|
||||
throwUnknownNode(node);
|
||||
|
||||
@@ -29,3 +29,13 @@ export class CompletionRecord implements TCompletionRecord {
|
||||
export function NormalCompletion(value?: TValue) {
|
||||
return new CompletionRecord('normal', value);
|
||||
}
|
||||
|
||||
export function v(cr: CompletionRecord): LanguageType | undefined {
|
||||
if (cr[TypeString] === 'normal') {
|
||||
return cr[ValueString];
|
||||
}
|
||||
// TODO: Else, from call site, return same value
|
||||
return undefined;
|
||||
}
|
||||
|
||||
export class AbruptCompletion extends TypeError {}
|
||||
|
||||
@@ -3,6 +3,7 @@ import { NumberString } from './typeNames';
|
||||
export interface TNumberValue {
|
||||
type: typeof NumberString;
|
||||
value: number;
|
||||
getValue(): number;
|
||||
}
|
||||
|
||||
export class NumberValue implements TNumberValue {
|
||||
@@ -13,4 +14,8 @@ export class NumberValue implements TNumberValue {
|
||||
this.type = NumberString;
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
getValue(): number {
|
||||
return this.value;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,6 +3,7 @@ import { StringString } from './typeNames';
|
||||
export interface TStringValue {
|
||||
type: typeof StringString;
|
||||
value: string;
|
||||
getValue(): string;
|
||||
}
|
||||
|
||||
export class StringValue implements TStringValue {
|
||||
@@ -13,4 +14,8 @@ export class StringValue implements TStringValue {
|
||||
this.type = StringString;
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
getValue(): string {
|
||||
return this.value;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user