Skip to content

Commit

Permalink
add array and reference stuff
Browse files Browse the repository at this point in the history
  • Loading branch information
MESYETI committed Nov 25, 2023
1 parent a476974 commit 6e2029b
Show file tree
Hide file tree
Showing 7 changed files with 235 additions and 74 deletions.
9 changes: 9 additions & 0 deletions examples/array.wpl
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
(myArray = [1 2 3 4]) ;
(myArray + 5) ;
(length = (myArray - 0)) ;
(i = 0) ;
({i < length} @ {
(stdout .d ((myArray : i) : 0)) ;
(stdout .s "\n") ;
(i = (i + 1))
})
153 changes: 95 additions & 58 deletions source/interpreter.d
Original file line number Diff line number Diff line change
Expand Up @@ -24,31 +24,31 @@ struct Operator {
ValueType right;
OperatorFunc func;
bool strict;
bool evalLeft;
bool evalRight;

this(string pname, ValueType pleft, ValueType pright, bool eLeft, bool eRight, OperatorFunc pfunc) {
this(string pname, ValueType pleft, ValueType pright, OperatorFunc pfunc) {
name = pname;
left = pleft;
right = pright;
func = pfunc;
evalLeft = eLeft;
evalRight = eRight;
strict = true;
strict = true;
}

this(string pname, OperatorFunc pfunc, bool eLeft, bool eRight) {
this(string pname, OperatorFunc pfunc) {
name = pname;
func = pfunc;
evalLeft = eLeft;
evalRight = eRight;
strict = false;
}
}

struct OpMeta {
bool evalLeft;
bool evalRight;
}

class Interpreter {
Variable[string] variables;
Operator[] ops;
OpMeta[string] opMeta;

this() {
// default variables
Expand All @@ -57,40 +57,61 @@ class Interpreter {
variables["stdin"] = Variable.Global(Value.File(stdin));

// strict operators
AddOp("+", ValueType.Integer, ValueType.Integer, true, true, &Operators.AddInt);
AddOp("-", ValueType.Integer, ValueType.Integer, true, true, &Operators.SubInt);
AddOp("*", ValueType.Integer, ValueType.Integer, true, true, &Operators.MulInt);
AddOp("/", ValueType.Integer, ValueType.Integer, true, true, &Operators.DivInt);
AddOp("^", ValueType.Integer, ValueType.Integer, true, true, &Operators.PowInt);
AddOp("%", ValueType.Integer, ValueType.Integer, true, true, &Operators.ModInt);
AddOp("<", ValueType.Integer, ValueType.Integer, true, true, &Operators.IntLess);
AddOp("<=", ValueType.Integer, ValueType.Integer, true, true, &Operators.IntLessE);
AddOp(">", ValueType.Integer, ValueType.Integer, true, true, &Operators.IntGreater);
AddOp(">=", ValueType.Integer, ValueType.Integer, true, true, &Operators.IntGreaterE);
AddOp(".s", ValueType.File, ValueType.String, true, true, &Operators.WriteString);
AddOp(".d", ValueType.File, ValueType.Integer, true, true, &Operators.WriteDecimal);
AddOp("==", ValueType.Integer, ValueType.Integer, true, true, &Operators.IntEquals);
AddOp("/=", ValueType.Integer, ValueType.Integer, true, true, &Operators.IntNotEquals);
AddOp("/=", ValueType.Integer, ValueType.Integer, true, true, &Operators.IntNotEquals);
AddOp("?", ValueType.Integer, ValueType.Lambda, true, true, &Operators.If);
AddOp(",", ValueType.File, ValueType.Integer, true, true, &Operators.Read);
AddOp(",n", ValueType.File, ValueType.Integer, true, true, &Operators.ReadLine);
AddOp("+", ValueType.String, ValueType.String, true, true, &Operators.AddString);
AddOp("==", ValueType.String, ValueType.String, true, true, &Operators.EqualsString);
AddOp("/=", ValueType.String, ValueType.String, true, true, &Operators.NotEqualsString);
AddOp("@", ValueType.Lambda, ValueType.Lambda, true, true, &Operators.While);
AddOp("+", ValueType.Integer, ValueType.Integer, &Operators.AddInt);
AddOp("-", ValueType.Integer, ValueType.Integer, &Operators.SubInt);
AddOp("*", ValueType.Integer, ValueType.Integer, &Operators.MulInt);
AddOp("/", ValueType.Integer, ValueType.Integer, &Operators.DivInt);
AddOp("^", ValueType.Integer, ValueType.Integer, &Operators.PowInt);
AddOp("%", ValueType.Integer, ValueType.Integer, &Operators.ModInt);
AddOp("<", ValueType.Integer, ValueType.Integer, &Operators.IntLess);
AddOp("<=", ValueType.Integer, ValueType.Integer, &Operators.IntLessE);
AddOp(">", ValueType.Integer, ValueType.Integer, &Operators.IntGreater);
AddOp(">=", ValueType.Integer, ValueType.Integer, &Operators.IntGreaterE);
AddOp(".s", ValueType.File, ValueType.String, &Operators.WriteString);
AddOp(".d", ValueType.File, ValueType.Integer, &Operators.WriteDecimal);
AddOp("==", ValueType.Integer, ValueType.Integer, &Operators.IntEquals);
AddOp("/=", ValueType.Integer, ValueType.Integer, &Operators.IntNotEquals);
AddOp("/=", ValueType.Integer, ValueType.Integer, &Operators.IntNotEquals);
AddOp("?", ValueType.Integer, ValueType.Lambda, &Operators.If);
AddOp(",", ValueType.File, ValueType.Integer, &Operators.Read);
AddOp(",n", ValueType.File, ValueType.Integer, &Operators.ReadLine);
AddOp("+", ValueType.String, ValueType.String, &Operators.AddString);
AddOp("==", ValueType.String, ValueType.String, &Operators.EqualsString);
AddOp("/=", ValueType.String, ValueType.String, &Operators.NotEqualsString);
AddOp("@", ValueType.Lambda, ValueType.Lambda, &Operators.While);
AddOp("+", ValueType.Array, ValueType.Integer, &Operators.AddArray);
AddOp("+", ValueType.Array, ValueType.String, &Operators.AddArray);
AddOp("+", ValueType.Array, ValueType.Lambda, &Operators.AddArray);
AddOp("+", ValueType.Array, ValueType.Array, &Operators.AddArray);
AddOp(":", ValueType.Array, ValueType.Integer, &Operators.ArrayIndex);
AddOp("-", ValueType.Array, ValueType.Integer, &Operators.ArrayLength);
AddOp(":=", ValueType.Reference, ValueType.Integer, &Operators.RefAssign);
AddOp(":=", ValueType.Reference, ValueType.String, &Operators.RefAssign);
AddOp(":=", ValueType.Reference, ValueType.Lambda, &Operators.RefAssign);
AddOp(":=", ValueType.Reference, ValueType.Array, &Operators.RefAssign);
AddOp(":", ValueType.Reference, ValueType.Integer, &Operators.DeRef);
AddOp(":", ValueType.Reference, ValueType.String, &Operators.DeRef);
AddOp(":", ValueType.Reference, ValueType.Lambda, &Operators.DeRef);
AddOp(":", ValueType.Reference, ValueType.Array, &Operators.DeRef);

// not strict operators
AddOp(";", &Operators.Chain, true, true);
AddOp("=", &Operators.Assign, false, true);
AddOp(";", &Operators.Chain);
AddOp("=", &Operators.Assign);
SetOpMeta("=", false, true);
}

void AddOp(string name, ValueType left, ValueType right, bool eLeft, bool eRight, OperatorFunc func) {
ops ~= Operator(name, left, right, eLeft, eRight, func);
void AddOp(string name, ValueType left, ValueType right, OperatorFunc func) {
ops ~= Operator(name, left, right, func);
opMeta[name] = OpMeta(true, true);
}

void AddOp(string name, OperatorFunc func, bool eLeft, bool eRight) {
ops ~= Operator(name, func, eLeft, eRight);
void AddOp(string name, OperatorFunc func) {
ops ~= Operator(name, func);
opMeta[name] = OpMeta(true, true);
}

void SetOpMeta(string name, bool left, bool right) {
opMeta[name] = OpMeta(left, right);
}

void AssertVariable(string name, ErrorInfo info) {
Expand Down Expand Up @@ -129,34 +150,50 @@ class Interpreter {

return Value.Lambda(node.expr);
}
case NodeType.Array: {
auto node = cast(ArrayNode) pnode;
auto ret = Value.Array([]);

foreach (ref node2 ; node.values) {
ret.values ~= Evaluate(node2, true);
}

return ret;
}
case NodeType.Expression: {
auto node = cast(ExpressionNode) pnode;

// look for operator

Operator op;
Value left;
Value right;
bool found;
foreach (ref iop ; ops) {
if (iop.name == node.op) {
found = true;
op = iop;
break;
}
}
OpMeta meta;

Value left;
Value right;
if (node.op !in opMeta) goto opNotFound;

if (!found) goto opNotFound;
meta = opMeta[node.op];

left = Evaluate(node.left, op.evalLeft);
right = Evaluate(node.right, op.evalRight);

if (op.strict) {
if (
(op.left != left.type) ||
(op.right != right.type)
) {
found = false;
left = Evaluate(node.left, meta.evalLeft);
right = Evaluate(node.right, meta.evalRight);

foreach (ref iop ; ops) {
if (iop.strict) {
if (
(iop.name == node.op) &&
(iop.left == left.type) &&
(iop.right == right.type)
) {
found = true;
op = iop;
break;
}
}
else {
if (iop.name == node.op) {
found = true;
op = iop;
break;
}
}
}

Expand Down
2 changes: 1 addition & 1 deletion source/language.d
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,6 @@ module wpl.language;
class Language {
static const string[] operators = [
"+", "-", "*", "/", "^", "%", ".s", ".d", "=", "==", "/=", ";", ",", "?", ",n",
"@", "<", "<=", ">", ">="
"@", "<", "<=", ">", ">=", ":", ":="
];
}
12 changes: 12 additions & 0 deletions source/lexer.d
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@ enum TokenType {
RParen,
LCurly,
RCurly,
LSquare,
RSquare,
Operator,
Integer,
String,
Expand Down Expand Up @@ -142,6 +144,16 @@ class Lexer {
AddToken(TokenType.RCurly);
break;
}
case '[': {
AddReading();
AddToken(TokenType.LSquare);
break;
}
case ']': {
AddReading();
AddToken(TokenType.RSquare);
break;
}
case '#': {
while (code[i] != '\n') {
++ i;
Expand Down
41 changes: 40 additions & 1 deletion source/operators.d
Original file line number Diff line number Diff line change
Expand Up @@ -136,7 +136,7 @@ class Operators {
auto left = (cast(VariableValue) pleft).value;

env.variables[left] = Variable(pright, 0);
return Value.Reference(env.variables[left].value);
return Value.Reference(&env.variables[left].value);
}

static Value Read(Value pleft, Value pright, Interpreter env) {
Expand Down Expand Up @@ -197,4 +197,43 @@ class Operators {

return Value.Unit();
}

// array ops
static Value AddArray(Value pleft, Value pright, Interpreter env) {
auto left = cast(ArrayValue) pleft;

left.values ~= pright;
return left;
}

static Value ArrayIndex(Value pleft, Value pright, Interpreter env) {
auto left = cast(ArrayValue) pleft;
auto right = (cast(IntegerValue) pright).value;

if ((right >= left.values.length) || (right < 0)) {
throw new OperatorException("Array index out of bounds");
}

return Value.Reference(&left.values[right]);
}

static Value ArrayLength(Value pleft, Value pright, Interpreter env) {
auto left = cast(ArrayValue) pleft;
auto right = (cast(IntegerValue) pright).value;

return Value.Integer(left.values.length - right);
}

static Value RefAssign(Value pleft, Value pright, Interpreter env) {
auto left = cast(ReferenceValue) pleft;

return (*left.value) = pright;
}

static Value DeRef(Value pleft, Value pright, Interpreter env) {
auto left = cast(ReferenceValue) pleft;

if (left.value is null) return pright;
else return *left.value;
}
}
Loading

0 comments on commit 6e2029b

Please sign in to comment.