Skip to content

Commit

Permalink
refactor
Browse files Browse the repository at this point in the history
  • Loading branch information
marihachi committed Aug 22, 2023
1 parent 3168739 commit 1d0ec77
Show file tree
Hide file tree
Showing 6 changed files with 116 additions and 141 deletions.
44 changes: 22 additions & 22 deletions src/lib/running/binary-expr.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { UguisuError } from '../misc/errors.js';
import { ArithmeticOperator, EquivalentOperator, LogicalBinaryOperator, OrderingOperator } from '../syntax/node.js';
import { Token } from '../syntax/token.js';
import { createOk, EvalResult } from './result.js';
import { EvalResult, Complete } from './result.js';
import {
assertValue,
BoolValue,
Expand All @@ -22,10 +22,10 @@ export function evalLogicalBinaryOp(op: LogicalBinaryOperator, left: Value, righ
assertValue(right, 'BoolValue');
switch (op) {
case Token.And2: {
return createOk(createBoolValue(left && right));
return new Complete(createBoolValue(left && right));
}
case Token.Or2: {
return createOk(createBoolValue(left || right));
return new Complete(createBoolValue(left || right));
}
}
}
Expand All @@ -43,10 +43,10 @@ export function evalEquivalentBinaryOp(op: EquivalentOperator, left: Value, righ
assertValue(right, 'NumberValue');
switch (op) {
case Token.Eq2: {
return createOk(createBoolValue(left == right));
return new Complete(createBoolValue(left == right));
}
case Token.NotEq: {
return createOk(createBoolValue(left != right));
return new Complete(createBoolValue(left != right));
}
}
break;
Expand All @@ -56,10 +56,10 @@ export function evalEquivalentBinaryOp(op: EquivalentOperator, left: Value, righ
assertValue(right, 'BoolValue');
switch (op) {
case Token.Eq2: {
return createOk(createBoolValue(left == right));
return new Complete(createBoolValue(left == right));
}
case Token.NotEq: {
return createOk(createBoolValue(left != right));
return new Complete(createBoolValue(left != right));
}
}
break;
Expand All @@ -69,10 +69,10 @@ export function evalEquivalentBinaryOp(op: EquivalentOperator, left: Value, righ
assertValue(right, 'CharValue');
switch (op) {
case Token.Eq2: {
return createOk(createBoolValue(left == right));
return new Complete(createBoolValue(left == right));
}
case Token.NotEq: {
return createOk(createBoolValue(left != right));
return new Complete(createBoolValue(left != right));
}
}
break;
Expand All @@ -82,10 +82,10 @@ export function evalEquivalentBinaryOp(op: EquivalentOperator, left: Value, righ
assertValue(right, 'StringValue');
switch (op) {
case Token.Eq2: {
return createOk(createBoolValue(left == right));
return new Complete(createBoolValue(left == right));
}
case Token.NotEq: {
return createOk(createBoolValue(left != right));
return new Complete(createBoolValue(left != right));
}
}
break;
Expand All @@ -104,10 +104,10 @@ export function evalEquivalentBinaryOp(op: EquivalentOperator, left: Value, righ
assertValue(right, 'FunctionValue');
switch (op) {
case Token.Eq2: {
return createOk(createBoolValue(equalFunc(left, right)));
return new Complete(createBoolValue(equalFunc(left, right)));
}
case Token.NotEq: {
return createOk(createBoolValue(!equalFunc(left, right)));
return new Complete(createBoolValue(!equalFunc(left, right)));
}
}
break;
Expand All @@ -133,16 +133,16 @@ export function evalOrderingBinaryOp(op: OrderingOperator, left: Value, right: V
assertValue(right, 'NumberValue');
switch (op) {
case Token.LessThan: {
return createOk(createBoolValue(left < right));
return new Complete(createBoolValue(left < right));
}
case Token.LessThanEq: {
return createOk(createBoolValue(left <= right));
return new Complete(createBoolValue(left <= right));
}
case Token.GreaterThan: {
return createOk(createBoolValue(left > right));
return new Complete(createBoolValue(left > right));
}
case Token.GreaterThanEq: {
return createOk(createBoolValue(left >= right));
return new Complete(createBoolValue(left >= right));
}
}
break;
Expand All @@ -164,19 +164,19 @@ export function evalArithmeticBinaryOp(op: ArithmeticOperator, left: Value, righ
assertValue(right, 'NumberValue');
switch (op) {
case Token.Plus: {
return createOk(createNumberValue(left + right));
return new Complete(createNumberValue(left + right));
}
case Token.Minus: {
return createOk(createNumberValue(left - right));
return new Complete(createNumberValue(left - right));
}
case Token.Asterisk: {
return createOk(createNumberValue(left * right));
return new Complete(createNumberValue(left * right));
}
case Token.Slash: {
return createOk(createNumberValue(left / right));
return new Complete(createNumberValue(left / right));
}
case Token.Percent: {
return createOk(createNumberValue(left % right));
return new Complete(createNumberValue(left % right));
}
}
}
46 changes: 17 additions & 29 deletions src/lib/running/result.ts
Original file line number Diff line number Diff line change
@@ -1,44 +1,32 @@
import { Value } from './value.js';

export type EvalResult<T> =
| OkResult<T>
| ReturnResult
| BreakResult;
| Complete<T>
| Return
| Break;

export type OkResult<T> = {
code: 'ok',
value: T,
};

export type ReturnResult = {
code: 'return',
value: Value,
};

export type BreakResult = {
code: 'break',
};

export function createOk<T>(value: T): EvalResult<T> {
return { code: 'ok', value };
export class Complete<T> {
kind = 'Complete' as const;
constructor(public value: T) { }
}

export function createReturn<T>(value: Value): EvalResult<T> {
return { code: 'return', value };
export class Return {
kind = 'Return' as const;
constructor(public value: Value) { }
}

export function createBreak<T>(): EvalResult<T> {
return { code: 'break' };
export class Break {
kind = 'Break' as const;
}

export function isOk<T>(x: EvalResult<T>): x is OkResult<T> {
return (x.code == 'ok');
export function isComplete<T>(x: EvalResult<T>): x is Complete<T> {
return (x.kind === 'Complete');
}

export function isReturn(x: EvalResult<unknown>): x is ReturnResult {
return (x.code == 'return');
export function isReturn(x: EvalResult<unknown>): x is Return {
return (x.kind === 'Return');
}

export function isBreak(x: EvalResult<unknown>): x is BreakResult {
return (x.code == 'break');
export function isBreak(x: EvalResult<unknown>): x is Break {
return (x.kind === 'Break');
}
48 changes: 24 additions & 24 deletions src/lib/running/run.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ import {
} from './binary-expr.js';
import * as builtins from './builtins.js';
import { RunContext, RunningEnv, Symbol } from './common.js';
import { createOk, EvalResult, isReturn, isBreak, isOk, createReturn, createBreak } from './result.js';
import { EvalResult, isReturn, isBreak, isComplete, Complete, Return, Break } from './result.js';
import {
assertValue,
FunctionValue,
Expand Down Expand Up @@ -84,7 +84,7 @@ export function call(r: RunContext, func: FunctionValue, args: Value[]): Value {
const arg = args[i];
ctx.env.declare(param.name, arg);
}
let result: EvalResult<Value> = createOk(createNoneValue());
let result: EvalResult<Value> = new Complete(createNoneValue());
for (const step of func.user.node.body) {
if (isExprNode(step)) {
result = evalExpr(ctx, step);
Expand Down Expand Up @@ -112,7 +112,7 @@ export function call(r: RunContext, func: FunctionValue, args: Value[]): Value {

function evalBlock(r: RunContext, block: StepNode[]): EvalResult<Value> {
r.env.enter();
let result: EvalResult<Value> = createOk(createNoneValue());
let result: EvalResult<Value> = new Complete(createNoneValue());
for (let i = 0; i < block.length; i++) {
const step = block[i];
if (isExprNode(step)) {
Expand All @@ -122,7 +122,7 @@ function evalBlock(r: RunContext, block: StepNode[]): EvalResult<Value> {
}
const isFinalStep = (i == block.length - 1);
if (isFinalStep) {
result = createOk(stepResult.value);
result = new Complete(stepResult.value);
} else {
// ignore the value
}
Expand All @@ -146,7 +146,7 @@ function evalReferenceExpr(r: RunContext, expr: ExprNode): EvalResult<Symbol> {
if (symbol == null) {
throw new UguisuError(`identifier \`${expr.name}\` is not defined`);
}
return createOk(symbol);
return new Complete(symbol);
}
case 'FieldAccess': {
const target = evalExpr(r, expr.target);
Expand All @@ -158,7 +158,7 @@ function evalReferenceExpr(r: RunContext, expr: ExprNode): EvalResult<Symbol> {
if (field == null) {
throw new UguisuError('unknown field');
}
return createOk(field);
return new Complete(field);
}
case 'IndexAccess': {
const target = evalExpr(r, expr.target);
Expand All @@ -175,7 +175,7 @@ function evalReferenceExpr(r: RunContext, expr: ExprNode): EvalResult<Symbol> {
if (symbol == null) {
throw new UguisuError('index out of range');
}
return createOk(symbol);
return new Complete(symbol);
}
default: {
throw new UguisuError('unexpected expression');
Expand All @@ -187,23 +187,23 @@ function evalStatement(r: RunContext, statement: StatementNode): EvalResult<Valu
switch (statement.kind) {
case 'ExprStatement': {
evalExpr(r, statement.expr);
return createOk(createNoneValue());
return new Complete(createNoneValue());
}
case 'ReturnStatement': {
if (statement.expr != null) {
const result = evalExpr(r, statement.expr);
if (isOk(result)) {
return createReturn(result.value);
if (isComplete(result)) {
return new Return(result.value);
} else {
return result;
}
} else {
return createReturn(createNoneValue());
return new Return(createNoneValue());
}
break;
}
case 'BreakStatement': {
return createBreak();
return new Break();
}
case 'LoopStatement': {
while (true) {
Expand All @@ -214,7 +214,7 @@ function evalStatement(r: RunContext, statement: StatementNode): EvalResult<Valu
break;
}
}
return createOk(createNoneValue());
return new Complete(createNoneValue());
}
case 'VariableDecl': {
if (statement.body != null) {
Expand All @@ -229,7 +229,7 @@ function evalStatement(r: RunContext, statement: StatementNode): EvalResult<Valu
} else {
r.env.declare(statement.name);
}
return createOk(createNoneValue());
return new Complete(createNoneValue());
}
case 'AssignStatement': {
let target;
Expand Down Expand Up @@ -305,24 +305,24 @@ function evalStatement(r: RunContext, statement: StatementNode): EvalResult<Valu
break;
}
}
return createOk(createNoneValue());
return new Complete(createNoneValue());
}
}
}

function evalExpr(r: RunContext, expr: ExprNode): EvalResult<Value> {
switch (expr.kind) {
case 'NumberLiteral': {
return createOk(createNumberValue(expr.value));
return new Complete(createNumberValue(expr.value));
}
case 'BoolLiteral': {
return createOk(createBoolValue(expr.value));
return new Complete(createBoolValue(expr.value));
}
case 'CharLiteral': {
return createOk(createCharValue(expr.value));
return new Complete(createCharValue(expr.value));
}
case 'StringLiteral': {
return createOk(createStringValue(expr.value));
return new Complete(createStringValue(expr.value));
}
case 'StructExpr': {
const fields = new Map<string, Symbol>();
Expand All @@ -334,7 +334,7 @@ function evalExpr(r: RunContext, expr: ExprNode): EvalResult<Value> {
const symbol = new Symbol(result.value);
fields.set(field.name, symbol);
}
return createOk(createStructValue(fields));
return new Complete(createStructValue(fields));
}
case 'ArrayNode': {
const items: Symbol[] = [];
Expand All @@ -345,7 +345,7 @@ function evalExpr(r: RunContext, expr: ExprNode): EvalResult<Value> {
}
items.push(new Symbol(result.value));
}
return createOk(createArrayValue(items));
return new Complete(createArrayValue(items));
}
case 'Identifier':
case 'FieldAccess':
Expand All @@ -358,7 +358,7 @@ function evalExpr(r: RunContext, expr: ExprNode): EvalResult<Value> {
if (symbol.value == null) {
throw new UguisuError('symbol not defined');
}
return createOk(symbol.value);
return new Complete(symbol.value);
}
case 'BinaryOp': {
const left = evalExpr(r, expr.left);
Expand Down Expand Up @@ -390,7 +390,7 @@ function evalExpr(r: RunContext, expr: ExprNode): EvalResult<Value> {
assertValue(result.value, 'BoolValue');
switch (expr.operator) {
case Token.Not: {
return createOk(createBoolValue(!result.value));
return new Complete(createBoolValue(!result.value));
}
}
throw new UguisuError('unexpected operation');
Expand Down Expand Up @@ -424,7 +424,7 @@ function evalExpr(r: RunContext, expr: ExprNode): EvalResult<Value> {
}
args.push(arg.value);
}
return createOk(call(r, callee.value, args));
return new Complete(call(r, callee.value, args));
}
}
}
Loading

0 comments on commit 1d0ec77

Please sign in to comment.