Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion source/language.d
Original file line number Diff line number Diff line change
Expand Up @@ -31,14 +31,16 @@ final class AssignStatement : Statement
Type type;
VarExpression dest;
Expression expr;
bool isConst;

this (int lineId_, Type type_, VarExpression dest_, Expression expr_)
this (int lineId_, Type type_, VarExpression dest_, Expression expr_, bool isConst_ = false)
{
lineId = lineId_;
type = type_;
dest = dest_;
expr = expr_;
complexity = 1 + dest.complexity + expr.complexity;
isConst = isConst_;
}
}

Expand Down
16 changes: 14 additions & 2 deletions source/parser.d
Original file line number Diff line number Diff line change
Expand Up @@ -499,9 +499,21 @@ final class StatementParser
"indent does not match");
t.popFront ();


bool isConst = false;
if (!line.tokens.empty && line.tokens.front == "const")
{
isConst = true;
line.tokens.popFront();
}

auto var = cast (VarExpression) (parseExpression (line));
check (var !is null, line,
"assign statement detected but left side not parsed");
"assign statement detected but left side not parsed");
if (isConst && var.index !is null)
{
throw new Exception("cannot declare array element as constant");
}

check (!line.tokens.empty, line,
"expected assignment operator, found end of line");
Expand All @@ -528,7 +540,7 @@ final class StatementParser
check (line.tokens.empty, line,
"extra token at end of line: " ~ line.tokens.front);

return new AssignStatement (line.lineId, type, var, cur);
return new AssignStatement (line.lineId, type, var, cur, isConst);
}

Statement parseStatement (string prevIndent)
Expand Down
55 changes: 45 additions & 10 deletions source/runner.d
Original file line number Diff line number Diff line change
Expand Up @@ -110,7 +110,7 @@ class Runner
}
}

long * varAddress (string name, bool canCreate = false)
long * varAddress (string name, bool canCreate = false, bool isConst = false)
{
foreach_reverse (ref cur; state)
{
Expand All @@ -119,7 +119,7 @@ class Runner
if (cur.vars[name].isConst)
{
throw new Exception ("variable " ~ name ~
" is constant");
" is constant");
}
return &(cur.vars[name].value);
}
Expand All @@ -128,11 +128,11 @@ class Runner
{
throw new Exception ("no such variable: " ~ name);
}
state.back.vars[name] = Var (0);
state.back.vars[name] = Var (0, isConst);
return &(state.back.vars[name].value);
}

long * arrayAddress (string name, long index)
long * arrayAddress (string name, long index, bool isConst = false)
{
foreach_reverse (ref cur; state)
{
Expand All @@ -141,7 +141,7 @@ class Runner
if (cur.arrays[name].isConst)
{
throw new Exception ("array " ~ name ~
" is constant");
" is constant");
}
if (index < 0 ||
cur.arrays[name].contents.length <= index)
Expand Down Expand Up @@ -306,17 +306,17 @@ class Runner
assert (false);
}

long * getAddr (VarExpression dest, bool canCreate)
long * getAddr (VarExpression dest, bool canCreate, bool isConst = false)
{
long * res;
if (dest.index is null)
{
res = varAddress (dest.name, canCreate);
res = varAddress (dest.name, canCreate, isConst);
}
else
{
auto indexValue = evalExpression (dest.index);
res = arrayAddress (dest.name, indexValue);
res = arrayAddress (dest.name, indexValue, isConst);
}
return res;
}
Expand Down Expand Up @@ -372,7 +372,7 @@ class Runner
return;
}

auto addr = getAddr (cur.dest, true);
auto addr = getAddr (cur.dest, true, cur.isConst);

auto value = control.queues[otherId][id].pop ();
doAssign (cur, addr, value);
Expand Down Expand Up @@ -409,11 +409,17 @@ class Runner
{
if (cur.dest.name in curState.arrays)
{
if(cur.isConst)
throw new Exception
("array: array cannot be constant");
curState.arrays[cur.dest.name] =
Array (new long [values[0].to !(size_t)]);
return;
}
}
if(cur.isConst)
throw new Exception
("array: array cannot be constant");
state.back.arrays[cur.dest.name] =
Array (new long [values[0].to !(size_t)]);
}
Expand All @@ -438,8 +444,37 @@ class Runner
return;
}

if(isConst && type == Type.assign)
{
auto varExpr = cast(VarExpression)(expr);
if (varExpr !is null && varExpr.name == dest.name && varExpr.index is null)
{
throw new Exception
("cannot initialize constant " ~ dest.name ~ " with itself");
}
}

auto value = evalExpression (expr);
auto addr = getAddr (dest, type == Type.assign);
auto addr = getAddr (dest, type == Type.assign, isConst);



if(isConst && type == Type.assign)
{
auto varExpr = cast(VarExpression)(expr);
foreach_reverse(ref curState; state)
{

if(dest.name in curState.vars)
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Хмм, то есть мы можем сделать переменную константой в середине работы программы? Это странно, и выглядит скорее как баг, чем как фича...

В принципе я видел такую идиому в Rust. Но здесь, считаю, гораздо вероятнее, что программист ошибся и хотел создать новую константу во внутреннем контексте, чем что он хотел сделать константой существующую переменную.

{
if(dest.name in curState.vars && !curState.vars[dest.name].isConst)
throw new Exception
("redefinition of variable " ~ dest.name ~ " as constant");
curState.vars[dest.name].isConst = true;
break;
}
}
}
doAssign (cur0, addr, value);
delay = complexity;
return;
Expand Down
3 changes: 2 additions & 1 deletion syntax.txt
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ function <name> ( <parameter-list> ) : \n <statement-list>

<assignment> is
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Мы же обсуждали изменение вида

<assignment> is
<variable> <assign-op> <expression0>
+const <variable> <assign-op> <expression0>

Соответственно, тогда понятно, что в parser.d меняется одна функция: parseAssignStatement.
Сейчас в коде так и есть, а в грамматике какой-то дебош вместо этого =)

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Честно говоря, я не особо понимаю как работать с подобной грамматикой

<variable> <assign-op> <expression0>
const <variable> <assign-op> <expression0>

<variable> is
<name>
Expand Down Expand Up @@ -120,4 +121,4 @@ if <expression0> : \n <statement-list> \n <elif-block>
<elif-block> is
elif <expression0> : \n <statement-list>
elif <expression0> : \n <statement-list> \n else \n <statement-list>
elif <expression0> : \n <statement-list> \n <elif-block>
elif <expression0> : \n <statement-list> \n <elif-block>