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,14 +25,27 @@
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))

Check warning on line 35 in Yail.Shared/Objects/StructObj.cs

View workflow job for this annotation

GitHub Actions / build

Dereference of a possibly null reference.
ExceptionHelper.PrintError($"Data types must be equal.");

fields[variableName] = valueObj;
}

public Dictionary<string, ValueObj> Get()
{
return Value as Dictionary<string, ValueObj>;

Check warning on line 43 in Yail.Shared/Objects/StructObj.cs

View workflow job for this annotation

GitHub Actions / build

Possible null reference return.
}

public ValueObj Get(string propName)
{
if (!(Value as Dictionary<string, ValueObj>).TryGetValue(propName, out var val))

Check warning on line 48 in Yail.Shared/Objects/StructObj.cs

View workflow job for this annotation

GitHub Actions / build

Dereference of a possibly null reference.
{
throw new Exception($"Field '{propName}' was not present in '{Name}'");
}
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 @@

Console.Write(val);
}

public bool ValueEquals(object? obj)
{
if (obj is ValueObj other)
{
return Value.GetType() == other.Value.GetType() && DataType == other.DataType;

Check warning on line 85 in Yail.Shared/ValueObj.cs

View workflow job for this annotation

GitHub Actions / build

Dereference of a possibly null reference.

Check warning on line 85 in Yail.Shared/ValueObj.cs

View workflow job for this annotation

GitHub Actions / build

Dereference of a possibly null reference.
}
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;
Loading