Skip to content

Commit 22b987f

Browse files
committed
add index-or-create opcode, indexed function statements will now create table chains if required.
1 parent e816889 commit 22b987f

10 files changed

Lines changed: 78 additions & 9 deletions

File tree

Core/EVIL.Grammar/AST/Expressions/IndexerExpression.cs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,18 +12,21 @@ public sealed class IndexerExpression : Expression
1212

1313
public bool IsConditional { get; }
1414
public bool WillBeAssigned { get; }
15+
public bool CreateTableIfNonExistent { get; }
1516

1617
public IndexerExpression(
1718
Expression indexable,
1819
Expression keyExpression,
1920
bool isConditional,
20-
bool willBeAssigned)
21+
bool willBeAssigned,
22+
bool createTableIfNonExistent)
2123
{
2224
Indexable = indexable;
2325
KeyExpression = keyExpression;
2426

2527
IsConditional = isConditional;
2628
WillBeAssigned = willBeAssigned;
29+
CreateTableIfNonExistent = createTableIfNonExistent;
2730

2831
Reparent(Indexable, KeyExpression);
2932
}

Core/EVIL.Grammar/EVIL.Grammar.csproj

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
<TargetFramework>net9.0</TargetFramework>
44
<Nullable>enable</Nullable>
55

6-
<Version>8.1.0</Version>
6+
<Version>8.2.0</Version>
77

88
<IsPackable>false</IsPackable>
99
</PropertyGroup>

Core/EVIL.Grammar/Parser.Expression.Indexer.cs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77

88
public partial class Parser
99
{
10-
private IndexerExpression IndexerExpression(Expression indexable)
10+
private IndexerExpression IndexerExpression(Expression indexable, bool createTableIfNonExistent)
1111
{
1212
int line, col;
1313
Expression indexer;
@@ -80,7 +80,8 @@ private IndexerExpression IndexerExpression(Expression indexable)
8080
indexable,
8181
indexer,
8282
isConditional,
83-
CurrentToken.Type == TokenType.Assign)
83+
CurrentToken.Type == TokenType.Assign,
84+
createTableIfNonExistent)
8485
{ Line = line, Column = col };
8586
}
8687
}

Core/EVIL.Grammar/Parser.Expression.Postfix.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,7 @@ private Expression PostfixExpression()
6363
case TokenType.Elvis:
6464
case TokenType.ElvisArray:
6565
{
66-
node = IndexerExpression(node);
66+
node = IndexerExpression(node, false);
6767
break;
6868
}
6969

Core/EVIL.Grammar/Parser.Statement.Fn.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,7 @@ private Statement FnStatement()
5959

6060
while (CurrentToken.Type == TokenType.Dot)
6161
{
62-
expression = IndexerExpression(expression);
62+
expression = IndexerExpression(expression, true);
6363
}
6464

6565
primaryTarget = expression;

VirtualMachine/EVIL.Ceres/EVIL.Ceres.csproj

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
99
<EnableUnsafeBinaryFormatterSerialization>true</EnableUnsafeBinaryFormatterSerialization>
1010

11-
<Version>9.1.0</Version>
11+
<Version>9.2.0</Version>
1212

1313
<IsPackable>false</IsPackable>
1414
</PropertyGroup>

VirtualMachine/EVIL.Ceres/ExecutionEngine/Diagnostics/OpCode.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,7 @@ public enum OpCode : byte
6666
ELINIT,
6767
ELSET,
6868
INDEX,
69+
INOCT,
6970
TABCLN,
7071
YIELD,
7172
YRET,

VirtualMachine/EVIL.Ceres/ExecutionEngine/ExecutionUnit.cs

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1433,6 +1433,30 @@ public void Step()
14331433
break;
14341434
}
14351435

1436+
case OpCode.INOCT:
1437+
{
1438+
a = PopValue(); // Key
1439+
c = PopValue(); // Table
1440+
1441+
if (c.Type != DynamicValueType.Table)
1442+
{
1443+
throw new UnsupportedDynamicValueOperationException(
1444+
$"Attempt to index or create a table on an unsupported type '{c.Type}'"
1445+
);
1446+
}
1447+
1448+
var value = c.Index(a);
1449+
1450+
if (value == DynamicValue.Nil)
1451+
{
1452+
value = new Table();
1453+
c.SetEntry(a, value);
1454+
}
1455+
1456+
PushValue(value);
1457+
break;
1458+
}
1459+
14361460
case OpCode.TABCLN:
14371461
{
14381462
var isDeepClone = frame.FetchByte() > 0;

VirtualMachine/EVIL.Ceres/TranslationEngine/Compiler.Expression.Indexer.cs

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -32,14 +32,25 @@ protected override void Visit(IndexerExpression indexerExpression)
3232
Chunk.CodeGenerator.Emit(OpCode.JUMP, endIndexerLabel);
3333
Chunk.UpdateLabel(indexLabel, Chunk.CodeGenerator.IP);
3434
Visit(indexerExpression.KeyExpression);
35-
Chunk.CodeGenerator.Emit(OpCode.INDEX);
35+
36+
Chunk.CodeGenerator.Emit(
37+
indexerExpression.CreateTableIfNonExistent
38+
? OpCode.INOCT
39+
: OpCode.INDEX
40+
);
41+
3642
Chunk.UpdateLabel(endIndexerLabel, Chunk.CodeGenerator.IP);
3743
}
3844
else
3945
{
4046
Visit(indexerExpression.Indexable);
4147
Visit(indexerExpression.KeyExpression);
42-
Chunk.CodeGenerator.Emit(OpCode.INDEX);
48+
49+
Chunk.CodeGenerator.Emit(
50+
indexerExpression.CreateTableIfNonExistent
51+
? OpCode.INOCT
52+
: OpCode.INDEX
53+
);
4354
}
4455
}
4556
}

VirtualMachine/Tests/EVIL.Ceres.LanguageTests/tests/027_fn_indexed.vil

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,4 +27,33 @@ fn fn_indexed_byref {
2727

2828
assert.is_of_type(t.func, Function);
2929
assert.equal(t.func(10, 2), 20);
30+
}
31+
32+
#[test]
33+
fn fn_indexed_inoct_create_one {
34+
val a = { };
35+
36+
loc fn a.b.c(d) -> d * 2;
37+
38+
assert.is_of_type(a, Table);
39+
assert.is_of_type(a.b, Table);
40+
assert.is_of_type(a.b.c, Function);
41+
assert.equal(a.b.c(2), 4);
42+
}
43+
44+
#[test]
45+
fn fn_indexed_inoct_create_many {
46+
val a = { };
47+
48+
loc fn a.b.c.d.e.f.g.h(i, j, k) -> i + j + k;
49+
50+
assert.is_of_type(a, Table);
51+
assert.is_of_type(a.b, Table);
52+
assert.is_of_type(a.b.c, Table);
53+
assert.is_of_type(a.b.c.d, Table);
54+
assert.is_of_type(a.b.c.d.e, Table);
55+
assert.is_of_type(a.b.c.d.e.f, Table);
56+
assert.is_of_type(a.b.c.d.e.f.g, Table);
57+
assert.is_of_type(a.b.c.d.e.f.g.h, Function);
58+
assert.equal(a.b.c.d.e.f.g.h(1, 2, 3), 6);
3059
}

0 commit comments

Comments
 (0)