Adds Tables

This commit is contained in:
Deukhoofd 2018-11-17 19:13:05 +01:00
parent 4414534866
commit 6a396d6368
No known key found for this signature in database
GPG Key ID: B4C087AC81641654
10 changed files with 210 additions and 22 deletions

View File

@ -0,0 +1,29 @@
using System.Collections.Generic;
using System.Linq;
namespace Upsilon.BaseTypes
{
public class LuaTable : LuaType
{
private Dictionary<string, LuaType> _map;
public LuaTable()
{
_map = new Dictionary<string, LuaType>();
}
public LuaTable(Dictionary<string, LuaType> map)
{
_map = map;
}
public override Type Type => Type.Table;
public override object ToCSharpObject()
{
return _map.ToDictionary(x => x.Key, x => x.Value.ToCSharpObject());
}
}
}

View File

@ -78,6 +78,8 @@ namespace Upsilon.Binder
return BindVariableExpression((VariableExpressionSyntax) e);
case SyntaxKind.FunctionCallExpression:
return BindFunctionCallExpression((FunctionCallExpressionSyntax) e);
case SyntaxKind.TableExpression:
return BindTableExpression((TableExpressionSyntax) e);
case SyntaxKind.BadExpression:
break;
case SyntaxKind.ScriptUnit:
@ -352,5 +354,49 @@ namespace Upsilon.Binder
return new BoundReturnStatement(expression);
}
private BoundExpression BindTableExpression(TableExpressionSyntax e)
{
var keyType = Type.Unknown;
var valueType = Type.Unknown;
var currentKey = 0;
var dictionary = new Dictionary<string, BoundExpression>();
foreach (var expressionSyntax in e.Expressions)
{
if (expressionSyntax.Kind == SyntaxKind.AssignmentStatement)
{
var assignment = (AssignmentExpressionSyntax) expressionSyntax;
var key = assignment.Identifier.Name;
if (keyType == Type.Unknown)
keyType = Type.String;
if (dictionary.ContainsKey(key))
{
// TODO: Log
continue;
}
var bound = BindExpression(assignment.Expression);
if (valueType == Type.Unknown)
valueType = bound.Type;
dictionary.Add(key, bound);
}
else
{
var expression = (ExpressionSyntax) expressionSyntax;
currentKey++;
if (dictionary.ContainsKey(currentKey.ToString()))
{
// TODO: Log
continue;
}
if (keyType == Type.Unknown)
keyType = Type.Number;
var bound = BindExpression(expression);
if (valueType == Type.Unknown)
valueType = bound.Type;
dictionary.Add(currentKey.ToString(), bound);
}
}
return new BoundTableExpression(keyType, valueType, dictionary);
}
}
}

View File

@ -0,0 +1,24 @@
using System.Collections.Generic;
using System.Collections.Immutable;
using Upsilon.BaseTypes;
namespace Upsilon.Binder
{
public class BoundTableExpression : BoundExpression
{
public BoundTableExpression(Type keyType, Type valueType, Dictionary<string, BoundExpression> expressions)
{
KeyType = keyType;
ValueType = valueType;
Expressions = expressions;
}
public override BoundKind Kind => BoundKind.BoundTableExpression;
public override Type Type => Type.Table;
public Type KeyType { get; }
public Type ValueType { get; }
public Dictionary<string, BoundExpression> Expressions { get; }
}
}

View File

@ -9,6 +9,7 @@ namespace Upsilon.Binder
BoundUnaryExpression,
VariableExpression,
BoundFunctionCallExpression,
BoundTableExpression,
// Statements
BoundAssignmentStatement,
@ -18,6 +19,6 @@ namespace Upsilon.Binder
BoundElseStatement,
BoundFunctionStatement,
BoundPromise,
BoundReturnStatement
BoundReturnStatement,
}
}

View File

@ -68,6 +68,7 @@ namespace Upsilon.Evaluator
case BoundKind.BoundUnaryExpression:
case BoundKind.VariableExpression:
case BoundKind.BoundFunctionCallExpression:
case BoundKind.BoundTableExpression:
_lastValue = EvaluateExpression((BoundExpression) b);
break;
case BoundKind.BoundAssignmentStatement:
@ -135,6 +136,8 @@ namespace Upsilon.Evaluator
return EvaluateVariableExpression((BoundVariableExpression) e);
case BoundKind.BoundFunctionCallExpression:
return EvaluateBoundFunctionCallExpression((BoundFunctionCallExpression) e);
case BoundKind.BoundTableExpression:
return EvaluateTableExpression((BoundTableExpression) e);
default:
throw new NotImplementedException();
}
@ -287,5 +290,15 @@ namespace Upsilon.Evaluator
HasReturned = true;
}
private LuaType EvaluateTableExpression(BoundTableExpression e)
{
var dic = new Dictionary<string, LuaType>();
foreach (var boundExpression in e.Expressions)
{
var evaluated = EvaluateExpression(boundExpression.Value);
dic.Add(boundExpression.Key, evaluated);
}
return new LuaTable(dic);
}
}
}

View File

@ -0,0 +1,31 @@
using System.Collections.Generic;
using System.Collections.Immutable;
using Upsilon.Text;
namespace Upsilon.Parser
{
public sealed class TableExpressionSyntax : ExpressionSyntax
{
public TableExpressionSyntax(SyntaxToken openBrace, ImmutableArray<SyntaxNode> expressions, SyntaxToken closeBrace)
{
Expressions = expressions;
OpenBrace = openBrace;
CloseBrace = closeBrace;
Span = new TextSpan(OpenBrace.Span.Start, CloseBrace.Span.End - OpenBrace.Span.Start);
}
public override SyntaxKind Kind => SyntaxKind.TableExpression;
public SyntaxToken OpenBrace { get; }
public ImmutableArray<SyntaxNode> Expressions { get; }
public SyntaxToken CloseBrace { get; }
public override IEnumerable<SyntaxNode> ChildNodes()
{
yield return OpenBrace;
foreach (var e in Expressions)
yield return e;
yield return CloseBrace;
}
}
}

View File

@ -22,25 +22,8 @@ namespace Upsilon.Parser
return lexer.Lex();
}
private char Current
{
get
{
if (_position >= _text.Length)
return '\0';
return _text[_position];
}
}
private char Next
{
get
{
if (_position + 1 >= _text.Length)
return '\0';
return _text[_position + 1];
}
}
private char Current => _position >= _text.Length ? '\0' : _text[_position];
private char Next => _position + 1 >= _text.Length ? '\0' : _text[_position + 1];
private ImmutableArray<SyntaxToken> Lex()
@ -82,6 +65,10 @@ namespace Upsilon.Parser
return new SyntaxToken(SyntaxKind.OpenParenthesis, _position, "(", null);
case ')':
return new SyntaxToken(SyntaxKind.CloseParenthesis, _position, ")", null);
case '{':
return new SyntaxToken(SyntaxKind.OpenBrace, _position, "{", null);
case '}':
return new SyntaxToken(SyntaxKind.CloseBrace, _position, "}", null);
case ',':
return new SyntaxToken(SyntaxKind.Comma, _position, ",", null);
case '"':

View File

@ -230,6 +230,8 @@ namespace Upsilon.Parser
return ParseFunctionCallExpression();
var token = MatchToken(SyntaxKind.Identifier);
return new VariableExpressionSyntax((IdentifierToken) token);
case SyntaxKind.OpenBrace:
return ParseTable();
case SyntaxKind.NilKeyword:
var nilToken = MatchToken(SyntaxKind.NilKeyword);
return new LiteralExpressionSyntax(nilToken, null);
@ -284,5 +286,25 @@ namespace Upsilon.Parser
var stringToken = MatchToken(SyntaxKind.String);
return new LiteralExpressionSyntax(stringToken, stringToken.Value);
}
private ExpressionSyntax ParseTable()
{
var openBrace = MatchToken(SyntaxKind.OpenBrace);
var arrBuilder = ImmutableArray.CreateBuilder<SyntaxNode>();
bool lastCommaFound = true;
while (Current.Kind != SyntaxKind.CloseBrace)
{
if (!lastCommaFound)
break;
var parsed = ParseExpression();
arrBuilder.Add(parsed);
lastCommaFound = Current.Kind == SyntaxKind.Comma;
if (lastCommaFound) NextToken();
}
var closeBrace = MatchToken(SyntaxKind.CloseBrace);
return new TableExpressionSyntax(openBrace, arrBuilder.ToImmutable(), closeBrace);
}
}
}

View File

@ -21,6 +21,8 @@ namespace Upsilon.Parser
TildeEquals,
Comma,
String,
OpenBrace,
CloseBrace,
// key words
TrueKeyword,
@ -49,6 +51,7 @@ namespace Upsilon.Parser
VariableExpression,
FunctionCallExpression,
BadExpression,
TableExpression,
// script unit
ScriptUnit,
@ -60,6 +63,6 @@ namespace Upsilon.Parser
ElseIfStatement,
ElseStatement,
FunctionStatement,
ReturnStatement
ReturnStatement,
}
}

View File

@ -1,4 +1,6 @@
using System;
using System.Collections.Generic;
using System.Text;
using Upsilon;
using Upsilon.Evaluator;
@ -46,7 +48,8 @@ namespace Ycicle
if (evaluate == null)
continue;
Console.ForegroundColor = ConsoleColor.Cyan;
Console.WriteLine(evaluate);
Console.WriteLine(ParseEvaluated(evaluate));
Console.ResetColor();
}
}
@ -68,5 +71,34 @@ namespace Ycicle
Console.Write(message.LineAfterError());
Console.WriteLine();
}
private static string ParseEvaluated(object o, int jumps = 0)
{
var sb = new StringBuilder();
if (o is Dictionary<string, object> dic)
{
for (var i = 0; i < jumps; i++) sb.Append(" ");
sb.Append("{\n");
foreach (var (key, value) in dic)
{
for (var i = 0; i < jumps; i++) sb.Append(" ");
sb.Append(" {");
sb.Append("\"");
sb.Append(key);
sb.Append("\": ");
sb.Append(ParseEvaluated(value, jumps + 1));
sb.Append(" }");
sb.Append(",\n");
}
for (var i = 0; i < jumps; i++) sb.Append(" ");
sb.Append("}\n");
}
else
{
sb.Append(o.ToString());
}
return sb.ToString();
}
}
}