Skip to content

Commit

Permalink
Add Error core data type.
Browse files Browse the repository at this point in the history
  • Loading branch information
vddCore committed Apr 3, 2024
1 parent 9d5b9f6 commit d513608
Show file tree
Hide file tree
Showing 20 changed files with 225 additions and 2 deletions.
1 change: 1 addition & 0 deletions Core/EVIL.CommonTypes/TypeSystem/DynamicValueType.cs
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ public enum DynamicValueType
Array,
Fiber,
Chunk,
Error,
TypeCode,
NativeFunction,
NativeObject
Expand Down
15 changes: 15 additions & 0 deletions Core/EVIL.Grammar/AST/Expressions/ErrorExpression.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
using EVIL.Grammar.AST.Base;

namespace EVIL.Grammar.AST.Expressions
{
public class ErrorExpression : Expression
{
public TableExpression UserDataTable { get; }

public ErrorExpression(TableExpression userDataTable)
{
UserDataTable = userDataTable;
Reparent(UserDataTable);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -146,6 +146,13 @@ private ConstantExpression ConstantExpression()
return new TypeCodeConstant(DynamicValueType.Chunk)
{ Line = line, Column = col };
}
case TokenType.ErrorTypeCode:
{
var (line, col) = Match(Token.ErrorTypeCode);

return new TypeCodeConstant(DynamicValueType.Error)
{ Line = line, Column = col };
}
case TokenType.TypeCodeTypeCode:
{
var (line, col) = Match(Token.TypeCodeTypeCode);
Expand Down
17 changes: 17 additions & 0 deletions Core/EVIL.Grammar/Parsing/Expressions/Parser.ErrorExpression.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
using EVIL.Grammar.AST.Expressions;
using EVIL.Lexical;

namespace EVIL.Grammar.Parsing
{
public partial class Parser
{
private ErrorExpression ErrorExpression()
{
var (line, col) = Match(Token.Error);
var userData = TableExpression();

return new ErrorExpression(userData)
{ Line = line, Column = col };
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,10 @@ private Expression PrimaryExpression()
{
return ArrayExpression();
}
else if (token.Type == TokenType.Error)
{
return ErrorExpression();
}
else if (token.Type == TokenType.Ellipsis)
{
var (line, col) = Match(Token.Ellipsis);
Expand Down
2 changes: 2 additions & 0 deletions Core/EVIL.Grammar/Traversal/AstVisitor.cs
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ protected AstVisitor()
{ typeof(ThrowStatement), (n) => Visit((ThrowStatement)n) },
{ typeof(TableExpression), (n) => Visit((TableExpression)n) },
{ typeof(ArrayExpression), (n) => Visit((ArrayExpression)n) },
{ typeof(ErrorExpression), (n) => Visit((ErrorExpression)n) },
{ typeof(SelfExpression), (n) => Visit((SelfExpression)n) },
{ typeof(SelfFnExpression), (n) => Visit((SelfFnExpression)n) },
{ typeof(SelfInvocationExpression), (n) => Visit((SelfInvocationExpression)n) },
Expand Down Expand Up @@ -115,6 +116,7 @@ public virtual void Visit(AstNode node)
public abstract void Visit(ThrowStatement throwStatement);
public abstract void Visit(TableExpression tableExpression);
public abstract void Visit(ArrayExpression arrayExpression);
public abstract void Visit(ErrorExpression errorExpression);
public abstract void Visit(SelfExpression selfExpression);
public abstract void Visit(SelfFnExpression selfFnExpression);
public abstract void Visit(SelfInvocationExpression selfInvocationExpression);
Expand Down
2 changes: 2 additions & 0 deletions Core/EVIL.Lexical/Lexer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -416,6 +416,7 @@ private Token GetIdentifierOrKeyword()
"each" => Token.Each,
"array" => Token.Array,
"self" => Token.Self,
"error" => Token.Error,
"override" => Token.Override,
"Infinity" => Token.Infinity,
"NaN" => Token.NaN,
Expand All @@ -426,6 +427,7 @@ private Token GetIdentifierOrKeyword()
"Table" => Token.TableTypeCode,
"Array" => Token.ArrayTypeCode,
"Fiber" => Token.FiberTypeCode,
"Error" => Token.ErrorTypeCode,
"Function" => Token.ChunkTypeCode,
"Type" => Token.TypeCodeTypeCode,
"NativeFunction" => Token.NativeFunctionTypeCode,
Expand Down
2 changes: 2 additions & 0 deletions Core/EVIL.Lexical/Token.cs
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,7 @@ public override int GetHashCode()
public static readonly Token AttributeList = new(TokenType.AttributeList, TokenClass.Operator, "#[");
public static readonly Token Array = new(TokenType.Array, TokenClass.Operator, "array");
public static readonly Token Self = new(TokenType.Self, TokenClass.Operator, "self");
public static readonly Token Error = new(TokenType.Error, TokenClass.Operator, "error");
public static readonly Token In = new(TokenType.In, TokenClass.Operator, "in");
public static readonly Token NotIn = new(TokenType.NotIn, TokenClass.Operator, "!in");
public static readonly Token Is = new(TokenType.Is, TokenClass.Operator, "is");
Expand Down Expand Up @@ -150,6 +151,7 @@ public override int GetHashCode()
public static readonly Token ArrayTypeCode = new(TokenType.ArrayTypeCode, TokenClass.TypeCode, "Array");
public static readonly Token FiberTypeCode = new(TokenType.FiberTypeCode, TokenClass.TypeCode, "Fiber");
public static readonly Token ChunkTypeCode = new(TokenType.ChunkTypeCode, TokenClass.TypeCode, "Function");
public static readonly Token ErrorTypeCode = new(TokenType.ErrorTypeCode, TokenClass.TypeCode, "Error");
public static readonly Token TypeCodeTypeCode = new(TokenType.TypeCodeTypeCode, TokenClass.TypeCode, "Type");
public static readonly Token NativeFunctionTypeCode = new(TokenType.NativeFunctionTypeCode, TokenClass.TypeCode, "NativeFunction");
public static readonly Token NativeObjectTypeCode = new(TokenType.NativeObjectTypeCode, TokenClass.TypeCode, "NativeObject");
Expand Down
2 changes: 2 additions & 0 deletions Core/EVIL.Lexical/TokenType.cs
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,7 @@ public enum TokenType
RBracket,
Array,
Self,
Error,

AttributeList,
Identifier,
Expand Down Expand Up @@ -116,6 +117,7 @@ public enum TokenType
ArrayTypeCode,
FiberTypeCode,
ChunkTypeCode,
ErrorTypeCode,
TypeCodeTypeCode,
NativeFunctionTypeCode,
NativeObjectTypeCode,
Expand Down
3 changes: 3 additions & 0 deletions VirtualMachine/Ceres/Ceres.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -170,5 +170,8 @@
<Compile Update="TranslationEngine\Compiler.Statement.Try.cs">
<DependentUpon>Compiler.cs</DependentUpon>
</Compile>
<Compile Update="TranslationEngine\Compiler.Expression.Error.cs">
<DependentUpon>Compiler.cs</DependentUpon>
</Compile>
</ItemGroup>
</Project>
44 changes: 44 additions & 0 deletions VirtualMachine/Ceres/ExecutionEngine/Diagnostics/Error.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
using Ceres.ExecutionEngine.Collections;
using Ceres.ExecutionEngine.TypeSystem;

namespace Ceres.ExecutionEngine.Diagnostics
{
public class Error
{
private Table UserData { get; } = new();

public int Length => UserData.Length;

public DynamicValue this[DynamicValue key]
{
get => UserData[key];
set => UserData[key] = value;
}

public Error()
{
}

public Error(Table userData)
{
UserData = userData;
}

public Error(string message)
{
UserData["msg"] = message;
}

public Error(Table userData, string message)
{
UserData = userData;
UserData["msg"] = message;
}

public bool Contains(DynamicValue key)
=> UserData.Contains(key);

public bool IsDeeplyEqualTo(Error other)
=> UserData.IsDeeplyEqualTo(other.UserData);
}
}
3 changes: 2 additions & 1 deletion VirtualMachine/Ceres/ExecutionEngine/Diagnostics/OpCode.cs
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,7 @@ public enum OpCode : byte
OVERRIDE,
ENTER,
THROW,
LEAVE
LEAVE,
ERRNEW
}
}
15 changes: 15 additions & 0 deletions VirtualMachine/Ceres/ExecutionEngine/ExecutionUnit.cs
Original file line number Diff line number Diff line change
Expand Up @@ -1280,6 +1280,21 @@ public void Step()
break;
}

case OpCode.ERRNEW:
{
a = PopValue();

if (a.Type != DynamicValueType.Table)
{
throw new UnsupportedDynamicValueOperationException(
$"Attempt to create an Error out of a value type '{a.Type}'."
);
}

PushValue(new Error(a.Table!));
break;
}

default:
{
throw new VirtualMachineException($"Invalid opcode '{opCode}'.");
Expand Down
36 changes: 35 additions & 1 deletion VirtualMachine/Ceres/ExecutionEngine/TypeSystem/DynamicValue.cs
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ public struct DynamicValue : IEquatable<DynamicValue>
public Array? Array { get; }
public Fiber? Fiber { get; }
public Chunk? Chunk { get; }
public Error? Error { get; }
public DynamicValueType TypeCode { get; }
public NativeFunction? NativeFunction { get; }
public object? NativeObject { get; }
Expand Down Expand Up @@ -86,6 +87,12 @@ public DynamicValue(Chunk value)
Type = DynamicValueType.Chunk;
}

public DynamicValue(Error value)
{
Error = value;
Type = DynamicValueType.Error;
}

public DynamicValue(DynamicValueType value)
{
TypeCode = value;
Expand Down Expand Up @@ -137,6 +144,22 @@ public override string ToString()
sb.Append(" ");
sb.Append(Boolean);
break;

case DynamicValueType.Error:
{
var msg = Error!["msg"];

if (msg == DynamicValueType.String)
{
sb.Append($"'{msg.String}'");
}
else
{
sb.Append($"[{msg.Error!.Length} userdata record(s)]");
}

break;
}

case DynamicValueType.Nil:
break;
Expand All @@ -158,7 +181,8 @@ public bool Equals(DynamicValue other)
&& Equals(Table, other.Table)
&& Equals(Array, other.Array)
&& Equals(Fiber, other.Fiber)
&& Equals(Chunk, other.Chunk)
&& Equals(Chunk, other.Chunk)
&& Equals(Error, other.Error)
&& TypeCode == other.TypeCode
&& Equals(NativeFunction, other.NativeFunction);

Expand All @@ -178,6 +202,7 @@ public override int GetHashCode()
hashCode.Add(Array);
hashCode.Add(Fiber);
hashCode.Add(Chunk);
hashCode.Add(Error);
hashCode.Add(TypeCode);
hashCode.Add(NativeFunction);
hashCode.Add(NativeObject);
Expand All @@ -199,6 +224,7 @@ public override int GetHashCode()
public static implicit operator DynamicValue(Array value) => new(value);
public static implicit operator DynamicValue(Fiber value) => new(value);
public static implicit operator DynamicValue(Chunk value) => new(value);
public static implicit operator DynamicValue(Error value) => new(value);
public static implicit operator DynamicValue(DynamicValueType value) => new(value);
public static implicit operator DynamicValue(NativeFunction value) => new(value);
public static DynamicValue FromObject(object value) => new(value);
Expand Down Expand Up @@ -296,6 +322,14 @@ public static explicit operator Chunk(DynamicValue value)
return value.Chunk!;
}

public static explicit operator Error(DynamicValue value)
{
if (value.Type != DynamicValueType.Error)
throw new InvalidCastException($"Cannot cast dynamic type '{value.Type}' to an Error.");

return value.Error!;
}

public static explicit operator DynamicValueType(DynamicValue value)
{
if (value.Type != DynamicValueType.TypeCode)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,10 @@ public static DynamicValue SetEntry(this DynamicValue a, DynamicValue key, Dynam
{
a.Array![key] = value;
}
else if (a.Type == DynamicValueType.Error)
{
a.Error![key] = value;
}
else
{
throw new UnsupportedDynamicValueOperationException(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,11 @@ public static DynamicValue IsDeeplyEqualTo(this DynamicValue a, DynamicValue b)
return new(a.Array!.IsDeeplyEqualTo(b.Array!));
}

if (a.Type == DynamicValueType.Error && b.Type == DynamicValueType.Error)
{
return new(a.Error!.IsDeeplyEqualTo(b.Error!));
}

try
{
return IsEqualTo(a, b);
Expand All @@ -40,6 +45,11 @@ public static DynamicValue IsDeeplyNotEqualTo(this DynamicValue a, DynamicValue
{
return new(!a.Array!.IsDeeplyEqualTo(b.Array!));
}

if (a.Type == DynamicValueType.Error && b.Type == DynamicValueType.Error)
{
return new(!a.Error!.IsDeeplyEqualTo(b.Error!));
}

try
{
Expand Down Expand Up @@ -81,6 +91,9 @@ public static DynamicValue IsEqualTo(this DynamicValue a, DynamicValue b)
case DynamicValueType.Chunk:
return a.Chunk == b.Chunk;

case DynamicValueType.Error:
return a.Error == b.Error;

case DynamicValueType.TypeCode:
return a.TypeCode == b.TypeCode;

Expand Down Expand Up @@ -124,6 +137,9 @@ public static DynamicValue IsNotEqualTo(this DynamicValue a, DynamicValue b)
case DynamicValueType.Chunk:
return a.Chunk != b.Chunk;

case DynamicValueType.Error:
return a.Error != b.Error;

case DynamicValueType.TypeCode:
return a.TypeCode != b.TypeCode;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,17 @@ public static DynamicValue ConvertToString(this DynamicValue a)
}
case DynamicValueType.Chunk:
return $"Function[{a.Chunk!.Name}]({a.Chunk.ParameterCount})";
case DynamicValueType.Error:
{
if (a.Error!["msg"].Type == DynamicValueType.String)
{
return $"Error[{a.Error["msg"].String}]";
}
else
{
return $"Error[{a.Error.Length}]";
}
}
case DynamicValueType.TypeCode:
return a.TypeCode switch
{
Expand Down
Loading

0 comments on commit d513608

Please sign in to comment.