Skip to content
Merged
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
14 changes: 14 additions & 0 deletions Yail.Shared/Objects/StructObj.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using Yail.Shared.Abstract;
using Yail.Shared.Helpers;

namespace Yail.Shared.Objects;

Expand All @@ -24,6 +25,19 @@ public void Set(string variableName, ValueObj value)
Value = list;
}

public void Update(string variableName, ValueObj valueObj)
{
var fields = Get();

if (!fields.TryGetValue(variableName, out var prevValue))
ExceptionHelper.PrintError($"Variable '{variableName}' is not defined in struct '{Name}'");

if (!prevValue.ValueEquals(valueObj))
ExceptionHelper.PrintError($"Data types must be equal.");

fields[variableName] = valueObj;
}

public Dictionary<string, ValueObj> Get()
{
return Value as Dictionary<string, ValueObj>;
Expand Down
9 changes: 9 additions & 0 deletions Yail.Shared/ValueObj.cs
Original file line number Diff line number Diff line change
Expand Up @@ -77,4 +77,13 @@ public virtual void Print(bool newLine = false)

Console.Write(val);
}

public bool ValueEquals(object? obj)
{
if (obj is ValueObj other)
{
return Value.GetType() == other.Value.GetType() && DataType == other.DataType;
}
return false;
}
}
94 changes: 94 additions & 0 deletions Yail.Tests/StructTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -177,4 +177,98 @@ pub struct Point {
Assert.Pass();
}
}

[Test]
public void CreateStructWithCtor()
{
var code = @"
package main

pub struct Point {
var x i32;
var z i32;
var y i32;
}

var p = new Point() {
y = 2;
};
print(p.y);
";

var actual = RunCode(code);

Assert.That(actual, Is.EqualTo("2"));
}

[Test]
public void CreateStructWithCtorAndAssignValue()
{
var code = @"
package main

pub struct Point {
var x i32;
var z i32;
var y i32;
}

var p = new Point() {
y = 2;
};
println(p.y);
p.y = 3;
print(p.y);
";

var actual = RunCode(code);

Assert.That(actual, Is.EqualTo("2\n3"));
}

[Test]
public void CreateStructWithDefaultValue()
{
var code = @"
package main

pub struct Point {
var x i32;
var z i32;
var y i32 = 3;
}

var p = new Point();

print(p.y);
";

var actual = RunCode(code);

Assert.That(actual, Is.EqualTo("3"));
}

[Test]
public void CreateStructWithDefaultValue_ConstructorAssign()
{
var code = @"
package main

pub struct Point {
var x i32;
var z i32;
var y i32 = 3;
}

var p = new Point() {
y = 5;
};

print(p.y);
";

var actual = RunCode(code);

Assert.That(actual, Is.EqualTo("5"));
}
}
35 changes: 30 additions & 5 deletions Yail/ExpressionsVisitor.cs
Original file line number Diff line number Diff line change
Expand Up @@ -51,11 +51,18 @@ public sealed class ExpressionsVisitor : ExpressionsBaseVisitor<ValueObj?>
return null;
}

if (_currentStruct is not null)
{
if (!_instances.TryGetValue(_currentStruct, out var currStruct))
ExceptionHelper.PrintError($"Struct '{_currentStruct}' is not defined.");

(currStruct as StructObj)!.Update(variableName, value);
return null;
}

if (!_variables.TryGetValue(variableName, out var prevVal))
{
Console.ForegroundColor = ConsoleColor.Red;
Console.Error.WriteLine($"Variable '${variableName}' is not defined.");
Environment.Exit(1);
ExceptionHelper.PrintError($"Variable '${variableName}' is not defined.");
}

if (prevVal is IAccessible accessible)
Expand Down Expand Up @@ -1027,7 +1034,18 @@ public override ValueObj VisitStructBlock(ExpressionsParser.StructBlockContext c
var varName = structLine.variableDefine().IDENTIFIER().GetText();
var dataType = structLine.variableDefine().DATA_TYPES().GetText().ToDataType();

structObj.Set(varName, new ValueObj(dataType));
var expr = structLine.variableDefine().expression();

if (expr is not null)
{
var defaultVal = Visit(expr);

structObj.Set(varName, defaultVal);
}
else
{
structObj.Set(varName, new ValueObj(dataType));
}
}

if (!_instances.TryAdd(structObj.Name, structObj))
Expand All @@ -1038,6 +1056,7 @@ public override ValueObj VisitStructBlock(ExpressionsParser.StructBlockContext c
return structObj;
}

private string? _currentStruct;
public override ValueObj? VisitInstanceCreateExpr(ExpressionsParser.InstanceCreateExprContext context)
{
var instanceName = string.Empty;
Expand All @@ -1052,7 +1071,13 @@ public override ValueObj VisitStructBlock(ExpressionsParser.StructBlockContext c
{
instanceName = context.instanceCreate().IDENTIFIER(0).GetText();
}


if (context.instanceCreate().instanceBody() is not null)
{
_currentStruct = $"{packageName}::{instanceName}";
Visit(context.instanceCreate().instanceBody());
_currentStruct = null;
}

var valueObj = _instances[$"{packageName}::{instanceName}"];

Expand Down
8 changes: 6 additions & 2 deletions Yail/Grammar/Expressions.g4
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,10 @@ block: '{' line* '}';
structBody: '{' structLine* '}';
structLine: variableDefine ';';

// structs new calling 'new'
instanceBody: '{' instanceLine* '}';
instanceLine: assignment ';';

directive: '#' 'use' USE_IDENTIFIERS;

multiplyOp: '*' | '/' | '%';
Expand Down Expand Up @@ -67,7 +71,7 @@ packageDeclaration: 'package' IDENTIFIER;
usingDirective: 'using' IDENTIFIER;

variableDeclaration: 'var' IDENTIFIER '=' REFERENCE? expression;
variableDefine: 'var' IDENTIFIER DATA_TYPES;
variableDefine: 'var' IDENTIFIER DATA_TYPES ('=' expression)?;
functionDeclaration: (accessLevels)? 'funky' IDENTIFIER '(' (parameterList)? ')' DATA_TYPES block;

parameterList: parameter (',' parameter)*;
Expand Down Expand Up @@ -97,6 +101,6 @@ foreachBlock: FOREACH '(' 'var' IDENTIFIER 'in' expression ')' block;

structBlock: accessLevels? 'struct' IDENTIFIER structBody;

instanceCreate: 'new' (IDENTIFIER '::')? IDENTIFIER '(' (expression (',' expression)*)? ')';
instanceCreate: 'new' (IDENTIFIER '::')? IDENTIFIER '(' (expression (',' expression)*)? ')' instanceBody?;
instancePropAssign: IDENTIFIER '.' IDENTIFIER '=' expression;
instancePropCall: IDENTIFIER '.' IDENTIFIER;