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); return BindVariableExpression((VariableExpressionSyntax) e);
case SyntaxKind.FunctionCallExpression: case SyntaxKind.FunctionCallExpression:
return BindFunctionCallExpression((FunctionCallExpressionSyntax) e); return BindFunctionCallExpression((FunctionCallExpressionSyntax) e);
case SyntaxKind.TableExpression:
return BindTableExpression((TableExpressionSyntax) e);
case SyntaxKind.BadExpression: case SyntaxKind.BadExpression:
break; break;
case SyntaxKind.ScriptUnit: case SyntaxKind.ScriptUnit:
@ -352,5 +354,49 @@ namespace Upsilon.Binder
return new BoundReturnStatement(expression); 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, BoundUnaryExpression,
VariableExpression, VariableExpression,
BoundFunctionCallExpression, BoundFunctionCallExpression,
BoundTableExpression,
// Statements // Statements
BoundAssignmentStatement, BoundAssignmentStatement,
@ -18,6 +19,6 @@ namespace Upsilon.Binder
BoundElseStatement, BoundElseStatement,
BoundFunctionStatement, BoundFunctionStatement,
BoundPromise, BoundPromise,
BoundReturnStatement BoundReturnStatement,
} }
} }

View File

@ -68,6 +68,7 @@ namespace Upsilon.Evaluator
case BoundKind.BoundUnaryExpression: case BoundKind.BoundUnaryExpression:
case BoundKind.VariableExpression: case BoundKind.VariableExpression:
case BoundKind.BoundFunctionCallExpression: case BoundKind.BoundFunctionCallExpression:
case BoundKind.BoundTableExpression:
_lastValue = EvaluateExpression((BoundExpression) b); _lastValue = EvaluateExpression((BoundExpression) b);
break; break;
case BoundKind.BoundAssignmentStatement: case BoundKind.BoundAssignmentStatement:
@ -135,6 +136,8 @@ namespace Upsilon.Evaluator
return EvaluateVariableExpression((BoundVariableExpression) e); return EvaluateVariableExpression((BoundVariableExpression) e);
case BoundKind.BoundFunctionCallExpression: case BoundKind.BoundFunctionCallExpression:
return EvaluateBoundFunctionCallExpression((BoundFunctionCallExpression) e); return EvaluateBoundFunctionCallExpression((BoundFunctionCallExpression) e);
case BoundKind.BoundTableExpression:
return EvaluateTableExpression((BoundTableExpression) e);
default: default:
throw new NotImplementedException(); throw new NotImplementedException();
} }
@ -287,5 +290,15 @@ namespace Upsilon.Evaluator
HasReturned = true; 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(); return lexer.Lex();
} }
private char Current private char Current => _position >= _text.Length ? '\0' : _text[_position];
{ private char Next => _position + 1 >= _text.Length ? '\0' : _text[_position + 1];
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 ImmutableArray<SyntaxToken> Lex() private ImmutableArray<SyntaxToken> Lex()
@ -82,6 +65,10 @@ namespace Upsilon.Parser
return new SyntaxToken(SyntaxKind.OpenParenthesis, _position, "(", null); return new SyntaxToken(SyntaxKind.OpenParenthesis, _position, "(", null);
case ')': case ')':
return new SyntaxToken(SyntaxKind.CloseParenthesis, _position, ")", null); return new SyntaxToken(SyntaxKind.CloseParenthesis, _position, ")", null);
case '{':
return new SyntaxToken(SyntaxKind.OpenBrace, _position, "{", null);
case '}':
return new SyntaxToken(SyntaxKind.CloseBrace, _position, "}", null);
case ',': case ',':
return new SyntaxToken(SyntaxKind.Comma, _position, ",", null); return new SyntaxToken(SyntaxKind.Comma, _position, ",", null);
case '"': case '"':

View File

@ -230,6 +230,8 @@ namespace Upsilon.Parser
return ParseFunctionCallExpression(); return ParseFunctionCallExpression();
var token = MatchToken(SyntaxKind.Identifier); var token = MatchToken(SyntaxKind.Identifier);
return new VariableExpressionSyntax((IdentifierToken) token); return new VariableExpressionSyntax((IdentifierToken) token);
case SyntaxKind.OpenBrace:
return ParseTable();
case SyntaxKind.NilKeyword: case SyntaxKind.NilKeyword:
var nilToken = MatchToken(SyntaxKind.NilKeyword); var nilToken = MatchToken(SyntaxKind.NilKeyword);
return new LiteralExpressionSyntax(nilToken, null); return new LiteralExpressionSyntax(nilToken, null);
@ -284,5 +286,25 @@ namespace Upsilon.Parser
var stringToken = MatchToken(SyntaxKind.String); var stringToken = MatchToken(SyntaxKind.String);
return new LiteralExpressionSyntax(stringToken, stringToken.Value); 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, TildeEquals,
Comma, Comma,
String, String,
OpenBrace,
CloseBrace,
// key words // key words
TrueKeyword, TrueKeyword,
@ -49,6 +51,7 @@ namespace Upsilon.Parser
VariableExpression, VariableExpression,
FunctionCallExpression, FunctionCallExpression,
BadExpression, BadExpression,
TableExpression,
// script unit // script unit
ScriptUnit, ScriptUnit,
@ -60,6 +63,6 @@ namespace Upsilon.Parser
ElseIfStatement, ElseIfStatement,
ElseStatement, ElseStatement,
FunctionStatement, FunctionStatement,
ReturnStatement ReturnStatement,
} }
} }

View File

@ -1,4 +1,6 @@
using System; using System;
using System.Collections.Generic;
using System.Text;
using Upsilon; using Upsilon;
using Upsilon.Evaluator; using Upsilon.Evaluator;
@ -46,7 +48,8 @@ namespace Ycicle
if (evaluate == null) if (evaluate == null)
continue; continue;
Console.ForegroundColor = ConsoleColor.Cyan; Console.ForegroundColor = ConsoleColor.Cyan;
Console.WriteLine(evaluate);
Console.WriteLine(ParseEvaluated(evaluate));
Console.ResetColor(); Console.ResetColor();
} }
} }
@ -68,5 +71,34 @@ namespace Ycicle
Console.Write(message.LineAfterError()); Console.Write(message.LineAfterError());
Console.WriteLine(); 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();
}
} }
} }