Added code so far.

This commit is contained in:
arookas 2015-12-06 23:15:02 -05:00
parent 12301380a2
commit 4f1e820006
22 changed files with 3397 additions and 0 deletions

127
ast/nodes.cs Normal file
View file

@ -0,0 +1,127 @@
using System;
using System.Collections;
using System.Collections.Generic;
namespace arookas
{
public class sunSourceLocation
{
public string File { get; private set; }
public int Line { get; private set; }
public int Column { get; private set; }
public sunSourceLocation(string file, int line, int column)
{
File = file;
Line = line;
Column = column;
}
public override string ToString()
{
return String.Format("\"{0}\", ({1},{2})", File, Line, Column);
}
}
class sunNode : IEnumerable<sunNode>
{
List<sunNode> children;
public sunNode Parent { get; private set; }
public sunSourceLocation Location { get; private set; }
public int Count { get { return children.Count; } }
public sunNode this[int index] { get { return index >= 0 && index < Count ? children[index] : null; } }
public bool IsRoot { get { return Parent == null; } }
public bool IsBranch { get { return Count > 0; } }
public bool IsLeaf { get { return Count < 1; } }
public sunNode(sunSourceLocation location)
{
children = new List<sunNode>(5);
Location = location;
}
public void Add(sunNode node)
{
if (node == null)
{
throw new ArgumentNullException("node");
}
if (node.Parent != null)
{
node.Parent.Remove(node);
}
node.Parent = this;
children.Add(node);
}
public void Remove(sunNode node)
{
if (node == null)
{
throw new ArgumentNullException("node");
}
if (node.Parent == this)
{
children.Remove(node);
node.Parent = null;
}
}
public void Clear()
{
foreach (var child in this)
{
child.Parent = null;
}
children.Clear();
}
public virtual void Compile(sunContext context)
{
// Simply compile all children nodes by default. This is here for the transcient nodes' implementations
// (sunStatement, sunCompoundStatement, etc.) so I only have to type this once. sunExpression is careful
// to override this with the custom shunting-yard algorithm implementation.
foreach (var child in this)
{
child.Compile(context);
}
}
protected bool TryCompile(sunNode node, sunContext context)
{
if (node != null)
{
node.Compile(context);
return true;
}
return false;
}
public IEnumerator<sunNode> GetEnumerator() { return children.GetEnumerator(); }
IEnumerator IEnumerable.GetEnumerator() { return GetEnumerator(); }
}
abstract class sunToken<TValue> : sunNode
{
public TValue Value { get; private set; }
protected sunToken(sunSourceLocation location, string token)
: base(location)
{
Value = ParseValue(token);
}
protected abstract TValue ParseValue(string token);
}
abstract class sunRawToken : sunToken<string>
{
protected sunRawToken(sunSourceLocation location, string token)
: base(location, token)
{
}
protected override string ParseValue(string token) { return token; }
}
}

122
ast/nodes.expressions.cs Normal file
View file

@ -0,0 +1,122 @@
using System.Collections;
using System.Collections.Generic;
using System.Linq;
namespace arookas
{
class sunExpression : sunNode
{
public sunExpression(sunSourceLocation location)
: base(location)
{
}
public override void Compile(sunContext context)
{
Stack<sunOperator> operatorStack = new Stack<sunOperator>(32);
AnalyzeExpression(context, this, operatorStack);
}
void AnalyzeExpression(sunContext context, sunExpression expression, Stack<sunOperator> operatorStack)
{
// this implementation assumes that the expression production child list alternates between operand and operator
// we can safely assume this as the grammar "operand {binary_operator operand}" enforces it
int stackCount = operatorStack.Count;
foreach (var node in expression)
{
if (node is sunOperand)
{
var operand = node as sunOperand;
// term
var term = operand.Term;
if (term is sunExpression)
{
AnalyzeExpression(context, term as sunExpression, operatorStack);
}
else
{
term.Compile(context);
}
var unaryOperators = operand.UnaryOperators;
if (unaryOperators != null)
{
unaryOperators.Compile(context);
}
}
else if (node is sunOperator)
{
var operatorNode = node as sunOperator;
while (operatorStack.Count > stackCount &&
(operatorNode.IsLeftAssociative && operatorNode.Precedence <= operatorStack.Peek().Precedence) ||
(operatorNode.IsRightAssociative && operatorNode.Precedence < operatorStack.Peek().Precedence))
{
operatorStack.Pop().Compile(context);
}
operatorStack.Push(operatorNode);
}
}
while (operatorStack.Count > stackCount)
{
operatorStack.Pop().Compile(context);
}
}
}
class sunOperand : sunNode
{
public sunNode UnaryOperators { get { return Count > 1 ? this[0] : null; } }
public sunNode Term { get { return this[Count - 1]; } }
public sunOperand(sunSourceLocation location)
: base(location)
{
}
// operands are compiled in sunExpression.Compile
}
class sunUnaryOperatorList : sunNode
{
public sunUnaryOperatorList(sunSourceLocation location)
: base(location)
{
}
public override void Compile(sunContext context)
{
foreach (var child in this.Reverse())
{
// compile unary operators in reverse order
child.Compile(context);
}
}
}
class sunTernaryOperator : sunNode
{
public sunExpression Condition { get { return this[0] as sunExpression; } }
public sunExpression TrueBody { get { return this[1] as sunExpression; } }
public sunExpression FalseBody { get { return this[2] as sunExpression; } }
public sunTernaryOperator(sunSourceLocation node)
: base(node)
{
}
public override void Compile(sunContext context)
{
Condition.Compile(context);
var falsePrologue = context.Text.GotoIfZero();
TrueBody.Compile(context);
var trueEpilogue = context.Text.Goto();
context.Text.ClosePoint(falsePrologue);
FalseBody.Compile(context);
context.Text.ClosePoint(trueEpilogue);
}
}
}

224
ast/nodes.flow.cs Normal file
View file

@ -0,0 +1,224 @@
using PerCederberg.Grammatica.Runtime;
using System.Linq;
namespace arookas
{
class sunIf : sunNode
{
public sunExpression Condition { get { return this[0] as sunExpression; } }
public sunNode TrueBody { get { return this[1]; } }
public sunNode FalseBody { get { return this[2]; } }
public sunIf(sunSourceLocation location)
: base(location)
{
}
public override void Compile(sunContext context)
{
Condition.Compile(context);
var trueBodyEpilogue = context.Text.GotoIfZero();
TrueBody.Compile(context);
var falseBody = FalseBody;
if (falseBody != null)
{
var falseBodyEpilogue = context.Text.Goto();
context.Text.ClosePoint(trueBodyEpilogue);
falseBody.Compile(context);
context.Text.ClosePoint(falseBodyEpilogue);
}
else
{
context.Text.ClosePoint(trueBodyEpilogue);
}
}
}
abstract class sunLoop : sunNode
{
public bool IsNamed { get { return NameLabel != null; } }
public sunNameLabel NameLabel { get { return this[0] as sunNameLabel; } }
protected sunLoop(sunSourceLocation location)
: base(location)
{
}
}
class sunWhile : sunLoop
{
public sunExpression Condition { get { return this[Count - 2] as sunExpression; } }
public sunNode Body { get { return this[Count - 1]; } }
public sunWhile(sunSourceLocation location)
: base(location)
{
}
public override void Compile(sunContext context)
{
context.Loops.Push(IsNamed ? NameLabel.Label.Value : null);
var bodyPrologue = context.Text.OpenPoint();
var continuePoint = context.Text.OpenPoint();
Condition.Compile(context);
var bodyEpilogue = context.Text.GotoIfZero();
Body.Compile(context);
context.Text.Goto(bodyPrologue);
context.Text.ClosePoint(bodyEpilogue);
var breakPoint = context.Text.OpenPoint();
context.Loops.Pop(context, breakPoint, continuePoint);
}
}
class sunDo : sunLoop
{
public sunNode Body { get { return this[Count - 2]; } }
public sunExpression Condition { get { return this[Count - 1] as sunExpression; } }
public sunDo(sunSourceLocation location)
: base(location)
{
}
public override void Compile(sunContext context)
{
context.Loops.Push(IsNamed ? NameLabel.Label.Value : null);
var bodyPrologue = context.Text.OpenPoint();
Body.Compile(context);
var continuePoint = context.Text.OpenPoint();
Condition.Compile(context);
var bodyEpilogue = context.Text.GotoIfZero();
context.Text.Goto(bodyPrologue);
context.Text.ClosePoint(bodyEpilogue);
var breakPoint = context.Text.OpenPoint();
context.Loops.Pop(context, breakPoint, continuePoint);
}
}
class sunFor : sunLoop
{
public sunForDeclaration Declaration { get { return this.FirstOrDefault(i => i is sunForDeclaration) as sunForDeclaration; } }
public sunForCondition Condition { get { return this.FirstOrDefault(i => i is sunForCondition) as sunForCondition; } }
public sunForIteration Iteration { get { return this.FirstOrDefault(i => i is sunForIteration) as sunForIteration; } }
public sunNode Body { get { return this[Count - 1]; } }
public sunFor(sunSourceLocation location)
: base(location)
{
}
public override void Compile(sunContext context)
{
context.Scopes.Push();
context.Loops.Push(IsNamed ? NameLabel.Label.Value : null);
TryCompile(Declaration, context);
var bodyPrologue = context.Text.OpenPoint();
TryCompile(Condition, context);
var bodyEpilogue = context.Text.GotoIfZero();
Body.Compile(context);
var continuePoint = context.Text.OpenPoint();
TryCompile(Iteration, context);
context.Text.Goto(bodyPrologue);
context.Text.ClosePoint(bodyEpilogue);
var breakPoint = context.Text.OpenPoint();
context.Loops.Pop(context, breakPoint, continuePoint);
context.Scopes.Pop();
}
}
class sunForDeclaration : sunNode
{
public sunForDeclaration(sunSourceLocation location)
: base(location)
{
}
}
class sunForCondition : sunNode
{
public sunForCondition(sunSourceLocation location)
: base(location)
{
}
}
class sunForIteration : sunNode
{
public sunForIteration(sunSourceLocation location)
: base(location)
{
}
}
class sunReturn : sunNode
{
public sunExpression Expression { get { return this[0] as sunExpression; } }
public sunReturn(sunSourceLocation location)
: base(location)
{
}
public override void Compile(sunContext context)
{
var expression = Expression;
if (expression != null)
{
expression.Compile(context);
context.Text.ReturnValue();
}
else
{
context.Text.ReturnVoid();
}
}
}
class sunBreak : sunNode
{
public bool IsNamed { get { return Count > 0; } }
public sunIdentifier NameLabel { get { return this[0] as sunIdentifier; } }
public sunBreak(sunSourceLocation location)
: base(location)
{
}
public override void Compile(sunContext context)
{
var point = context.Text.Goto();
if (!context.Loops.AddBreak(point, IsNamed ? NameLabel.Value : null))
{
throw new sunBreakException(this);
}
}
}
class sunContinue : sunNode
{
public bool IsNamed { get { return Count > 0; } }
public sunIdentifier NameLabel { get { return this[0] as sunIdentifier; } }
public sunContinue(sunSourceLocation location)
: base(location)
{
}
public override void Compile(sunContext context)
{
var point = context.Text.Goto();
if (!context.Loops.AddContinue(point, IsNamed ? NameLabel.Value : null))
{
throw new sunContinueException(this);
}
}
}
}

95
ast/nodes.functions.cs Normal file
View file

@ -0,0 +1,95 @@
using System.Collections.Generic;
using System.Linq;
namespace arookas
{
class sunBuiltinDeclaration : sunNode
{
public sunIdentifier Builtin { get { return this[0] as sunIdentifier; } }
public sunParameterList Parameters { get { return this[1] as sunParameterList; } }
public sunBuiltinDeclaration(sunSourceLocation location)
: base(location)
{
}
public override void Compile(sunContext context)
{
context.DeclareBuiltin(this);
}
}
class sunFunctionDefinition : sunNode
{
public sunIdentifier Function { get { return this[0] as sunIdentifier; } }
public sunParameterList Parameters { get { return this[1] as sunParameterList; } }
public sunNode Body { get { return this[2]; } }
public sunFunctionDefinition(sunSourceLocation location)
: base(location)
{
}
public override void Compile(sunContext context)
{
context.DefineFunction(this); // possibly counter intuitively, this defines the function in the context; it doesn't compile the definition body
}
}
class sunFunctionCall : sunNode
{
public sunIdentifier Function { get { return this[0] as sunIdentifier; } }
public sunNode Arguments { get { return this[1] as sunNode; } }
bool IsStatement { get { return !(Parent is sunOperand); } }
public sunFunctionCall(sunSourceLocation location)
: base(location)
{
}
public override void Compile(sunContext context)
{
var callableInfo = context.ResolveCallable(this);
if (!callableInfo.Parameters.ValidateArgumentCount(Arguments.Count))
{
throw new sunArgumentCountException(this, callableInfo);
}
Arguments.Compile(context);
callableInfo.OpenCallSite(context, Arguments.Count);
if (IsStatement)
{
context.Text.Pop();
}
}
}
class sunParameterList : sunNode
{
public IEnumerable<sunIdentifier> Parameters { get { return this.OfType<sunIdentifier>(); } }
public bool IsVariadic { get { return Count > 0 && this[Count - 1] is sunEllipsis; } }
public sunParameterInfo ParameterInfo { get { return new sunParameterInfo(Parameters, IsVariadic); } }
public sunParameterList(sunSourceLocation location)
: base(location)
{
int count = this.Count(i => i is sunEllipsis);
if (count > 1 || (count > 0 && !(this[Count - 1] is sunEllipsis)))
{
throw new sunVariadicParameterListException(this);
}
}
}
class sunEllipsis : sunNode
{
public sunEllipsis(sunSourceLocation location)
: base(location)
{
}
}
}

201
ast/nodes.literals.cs Normal file
View file

@ -0,0 +1,201 @@
using System;
using System.Globalization;
using System.Text;
namespace arookas
{
class sunIntLiteral : sunToken<int> // base-10 integer
{
public sunIntLiteral(sunSourceLocation location, string token)
: base(location, token)
{
}
protected override int ParseValue(string token) { return Int32.Parse(token); }
public override void Compile(sunContext context)
{
context.Text.PushInt(Value);
}
}
class sunHexLiteral : sunIntLiteral // base-16 integer
{
public sunHexLiteral(sunSourceLocation location, string token)
: base(location, token)
{
}
protected override int ParseValue(string token)
{
// because .NET's hex parsing is gay and doesn't support
// leading signs, manually detect negative literals
var neg = (token[0] == '-');
var trim = neg ? 3 : 2;
var digits = token.Substring(trim); // trim the '0x' prefix before parsing
var value = Int32.Parse(token.Substring(2), NumberStyles.AllowHexSpecifier);
if (neg)
{
value = -value;
}
return value;
}
}
class sunFloatLiteral : sunToken<float>
{
public sunFloatLiteral(sunSourceLocation location, string token)
: base(location, token)
{
}
protected override float ParseValue(string image) { return Single.Parse(image); }
public override void Compile(sunContext context)
{
context.Text.PushFloat(Value);
}
}
class sunStringLiteral : sunToken<string>
{
public sunStringLiteral(sunSourceLocation location, string token)
: base(location, token)
{
}
protected override string ParseValue(string image) { return UnescapeString(image.Substring(1, image.Length - 2)); } // remove enclosing quotes
public override void Compile(sunContext context)
{
context.Text.PushData(context.DataTable.Add(Value));
}
// string unescaping utility
string UnescapeString(string value)
{
// based on Hans Passant's code
StringBuilder sb = new StringBuilder(value.Length);
for (int i = 0; i < value.Length;)
{
int j = value.IndexOf('\\', i);
if (j < 0 || j >= value.Length - 1)
{
j = value.Length;
}
sb.Append(value, i, j - i);
if (j >= value.Length)
{
break;
}
switch (value[j + 1])
{
case '\'': sb.Append('\''); break;
case '"': sb.Append('"'); break;
case '\\': sb.Append('\\'); break;
case '0': sb.Append('\0'); break;
case 'a': sb.Append('\a'); break;
case 'b': sb.Append('\b'); break;
case 'f': sb.Append('\f'); break;
case 'n': sb.Append('n'); break;
case 't': sb.Append('\t'); break;
case 'v': sb.Append('\v'); break;
case 'x': sb.Append(UnescapeHex(value, j + 2, out i)); continue;
case 'u': sb.Append(UnescapeUnicodeCodeUnit(value, j + 2, out i)); continue;
case 'U': sb.Append(UnescapeUnicodeSurrogatePair(value, j + 2, out i)); continue;
default: throw new sunEscapeSequenceException(this);
}
i = j + 2;
}
return sb.ToString();
}
char UnescapeHex(string value, int start, out int end)
{
if (start > value.Length)
{
throw new sunEscapeSequenceException(this); // we need at least one digit
}
StringBuilder sb = new StringBuilder(4);
int digits = 0;
while (digits < 4 && start < value.Length && IsHexDigit(value[start]))
{
sb.Append(value[start]);
++digits;
++start;
}
end = start;
return (char)Int32.Parse(sb.ToString(), NumberStyles.AllowHexSpecifier);
}
char UnescapeUnicodeCodeUnit(string value, int start, out int end)
{
if (start >= value.Length - 4)
{
throw new sunEscapeSequenceException(this); // we need four digits
}
end = start + 4;
return (char)Int32.Parse(value.Substring(start, 4), NumberStyles.AllowHexSpecifier);
}
string UnescapeUnicodeSurrogatePair(string value, int start, out int end)
{
if (start >= value.Length - 8)
{
throw new sunEscapeSequenceException(this); // we need eight digits
}
char high = (char)Int32.Parse(value.Substring(start, 4), NumberStyles.AllowHexSpecifier);
char low = (char)Int32.Parse(value.Substring(start + 4, 4), NumberStyles.AllowHexSpecifier);
if (!Char.IsHighSurrogate(high) || !Char.IsLowSurrogate(low))
{
throw new sunEscapeSequenceException(this); // characters are not a surrogate pair
}
end = start + 8;
return String.Concat(high, low);
}
static bool IsHexDigit(char c)
{
return (c >= '0' && c <= '9') ||
(c >= 'A' && c <= 'F') ||
(c >= 'a' && c <= 'f');
}
}
class sunIdentifier : sunRawToken
{
public sunIdentifier(sunSourceLocation location, string token)
: base(location, token)
{
// make sure it is a valid identifier name (i.e. not a keyword)
if (sunParser.IsKeyword(Value))
{
throw new sunIdentifierException(this);
}
}
// identifiers are compiled on a per-context basis (i.e. at a higher level)
}
class sunTrue : sunIntLiteral
{
public sunTrue(sunSourceLocation location, string token)
: base(location, token)
{
}
protected override int ParseValue(string token) { return 1; }
}
class sunFalse : sunIntLiteral
{
public sunFalse(sunSourceLocation location, string token)
: base(location, token)
{
}
protected override int ParseValue(string token) { return 0; }
}
}

453
ast/nodes.operators.cs Normal file
View file

@ -0,0 +1,453 @@
using PerCederberg.Grammatica.Runtime;
namespace arookas
{
enum Associativity
{
Left,
Right,
}
abstract class sunOperator : sunNode
{
public virtual Associativity Associativity { get { return Associativity.Left; } }
public abstract int Precedence { get; }
public bool IsLeftAssociative { get { return Associativity == Associativity.Left; } }
public bool IsRightAssociative { get { return Associativity == Associativity.Right; } }
protected sunOperator(sunSourceLocation location)
: base(location)
{
}
}
// precedence 0
class sunLogOR : sunOperator
{
public override int Precedence { get { return 0; } }
public sunLogOR(sunSourceLocation location)
: base(location)
{
}
public override void Compile(sunContext context) { context.Text.LogOR(); }
}
// precedence 1
class sunLogAND : sunOperator
{
public override int Precedence { get { return 1; } }
public sunLogAND(sunSourceLocation location)
: base(location)
{
}
public override void Compile(sunContext context) { context.Text.LogAND(); }
}
// precedence 2
class sunBitOR : sunOperator
{
public override int Precedence { get { return 2; } }
public sunBitOR(sunSourceLocation location)
: base(location)
{
}
public override void Compile(sunContext context) { context.Text.BitOR(); }
}
// precedence 3
class sunBitAND : sunOperator
{
public override int Precedence { get { return 3; } }
public sunBitAND(sunSourceLocation location)
: base(location)
{
}
public override void Compile(sunContext context) { context.Text.BitAND(); }
}
// precedence 4
class sunEq : sunOperator
{
public override int Precedence { get { return 4; } }
public sunEq(sunSourceLocation location)
: base(location)
{
}
public override void Compile(sunContext context) { context.Text.Eq(); }
}
class sunNtEq : sunOperator
{
public override int Precedence { get { return 4; } }
public sunNtEq(sunSourceLocation location)
: base(location)
{
}
public override void Compile(sunContext context) { context.Text.NtEq(); }
}
// precedence 5
class sunLt : sunOperator
{
public override int Precedence { get { return 5; } }
public sunLt(sunSourceLocation location)
: base(location)
{
}
public override void Compile(sunContext context) { context.Text.Lt(); }
}
class sunLtEq : sunOperator
{
public override int Precedence { get { return 5; } }
public sunLtEq(sunSourceLocation location)
: base(location)
{
}
public override void Compile(sunContext context) { context.Text.LtEq(); }
}
class sunGt : sunOperator
{
public override int Precedence { get { return 5; } }
public sunGt(sunSourceLocation location)
: base(location)
{
}
public override void Compile(sunContext context) { context.Text.Gt(); }
}
class sunGtEq : sunOperator
{
public override int Precedence { get { return 5; } }
public sunGtEq(sunSourceLocation location)
: base(location)
{
}
public override void Compile(sunContext context) { context.Text.GtEq(); }
}
// precedence 6
class sunBitLsh : sunOperator
{
public override int Precedence { get { return 6; } }
public sunBitLsh(sunSourceLocation location)
: base(location)
{
}
public override void Compile(sunContext context) { context.Text.ShL(); }
}
class sunBitRsh : sunOperator
{
public override int Precedence { get { return 6; } }
public sunBitRsh(sunSourceLocation location)
: base(location)
{
}
public override void Compile(sunContext context) { context.Text.ShR(); }
}
// precedence 7
class sunAdd : sunOperator
{
public override int Precedence { get { return 7; } }
public sunAdd(sunSourceLocation location)
: base(location)
{
}
public override void Compile(sunContext context) { context.Text.Add(); }
}
class sunSub : sunOperator
{
public override int Precedence { get { return 7; } }
public sunSub(sunSourceLocation location)
: base(location)
{
}
public override void Compile(sunContext context) { context.Text.Sub(); }
}
// precedence 8
class sunMul : sunOperator
{
public override int Precedence { get { return 8; } }
public sunMul(sunSourceLocation location)
: base(location)
{
}
public override void Compile(sunContext context) { context.Text.Mul(); }
}
class sunDiv : sunOperator
{
public override int Precedence { get { return 8; } }
public sunDiv(sunSourceLocation location)
: base(location)
{
}
public override void Compile(sunContext context) { context.Text.Div(); }
}
class sunMod : sunOperator
{
public override int Precedence { get { return 8; } }
public sunMod(sunSourceLocation location)
: base(location)
{
}
public override void Compile(sunContext context) { context.Text.Mod(); }
}
// precedence 9
class sunLogNOT : sunOperator
{
public override int Precedence { get { return 9; } }
public sunLogNOT(sunSourceLocation location)
: base(location)
{
}
public override void Compile(sunContext context) { context.Text.LogNOT(); }
}
class sunNeg : sunOperator
{
public override int Precedence { get { return 9; } }
public sunNeg(sunSourceLocation location)
: base(location)
{
}
public override void Compile(sunContext context) { context.Text.Neg(); }
}
// assignment operators
class sunAssign : sunOperator
{
public override Associativity Associativity { get { return Associativity.Right; } }
public override int Precedence { get { return -1; } }
public sunAssign(sunSourceLocation location)
: base(location)
{
}
public virtual void Compile(sunContext context, sunVariableInfo variableInfo, sunExpression expression)
{
expression.Compile(context);
context.Text.StoreVariable(variableInfo);
}
}
class sunAssignAdd : sunAssign
{
public sunAssignAdd(sunSourceLocation location)
: base(location)
{
}
public override void Compile(sunContext context, sunVariableInfo variableInfo, sunExpression expression)
{
context.Text.PushVariable(variableInfo);
expression.Compile(context);
context.Text.Add();
context.Text.StoreVariable(variableInfo);
}
}
class sunAssignSub : sunAssign
{
public sunAssignSub(sunSourceLocation location)
: base(location)
{
}
public override void Compile(sunContext context, sunVariableInfo variableInfo, sunExpression expression)
{
context.Text.PushVariable(variableInfo);
expression.Compile(context);
context.Text.Sub();
context.Text.StoreVariable(variableInfo);
}
}
class sunAssignMul : sunAssign
{
public sunAssignMul(sunSourceLocation location)
: base(location)
{
}
public override void Compile(sunContext context, sunVariableInfo variableInfo, sunExpression expression)
{
context.Text.PushVariable(variableInfo);
expression.Compile(context);
context.Text.Mul();
context.Text.StoreVariable(variableInfo);
}
}
class sunAssignDiv : sunAssign
{
public sunAssignDiv(sunSourceLocation location)
: base(location)
{
}
public override void Compile(sunContext context, sunVariableInfo variableInfo, sunExpression expression)
{
context.Text.PushVariable(variableInfo);
expression.Compile(context);
context.Text.Div();
context.Text.StoreVariable(variableInfo);
}
}
class sunAssignMod : sunAssign
{
public sunAssignMod(sunSourceLocation location)
: base(location)
{
}
public override void Compile(sunContext context, sunVariableInfo variableInfo, sunExpression expression)
{
context.Text.PushVariable(variableInfo);
expression.Compile(context);
context.Text.Mod();
context.Text.StoreVariable(variableInfo);
}
}
class sunAssignBitAND : sunAssign
{
public sunAssignBitAND(sunSourceLocation location)
: base(location)
{
}
public override void Compile(sunContext context, sunVariableInfo variableInfo, sunExpression expression)
{
context.Text.PushVariable(variableInfo);
expression.Compile(context);
context.Text.BitAND();
context.Text.StoreVariable(variableInfo);
}
}
class sunAssignBitOR : sunAssign
{
public sunAssignBitOR(sunSourceLocation location)
: base(location)
{
}
public override void Compile(sunContext context, sunVariableInfo variableInfo, sunExpression expression)
{
context.Text.PushVariable(variableInfo);
expression.Compile(context);
context.Text.BitOR();
context.Text.StoreVariable(variableInfo);
}
}
class sunAssignBitLsh : sunAssign
{
public sunAssignBitLsh(sunSourceLocation location)
: base(location)
{
}
public override void Compile(sunContext context, sunVariableInfo variableInfo, sunExpression expression)
{
context.Text.PushVariable(variableInfo);
expression.Compile(context);
context.Text.ShL();
context.Text.StoreVariable(variableInfo);
}
}
class sunAssignBitRsh : sunAssign
{
public sunAssignBitRsh(sunSourceLocation location)
: base(location)
{
}
public override void Compile(sunContext context, sunVariableInfo variableInfo, sunExpression expression)
{
context.Text.PushVariable(variableInfo);
expression.Compile(context);
context.Text.ShR();
context.Text.StoreVariable(variableInfo);
}
}
}

50
ast/nodes.statements.cs Normal file
View file

@ -0,0 +1,50 @@
namespace arookas
{
class sunStatementBlock : sunNode
{
public sunStatementBlock(sunSourceLocation location)
: base(location)
{
}
public override void Compile(sunContext context)
{
context.Scopes.Push();
base.Compile(context);
context.Scopes.Pop();
}
}
class sunImport : sunNode
{
public sunStringLiteral ImportFile { get { return this[0] as sunStringLiteral; } }
public sunImport(sunSourceLocation location)
: base(location)
{
}
public override void Compile(sunContext context)
{
var file = context.Imports.ResolveImport(this);
if (file == null)
{
return; // the file has already been imported
}
context.Compile(file);
}
}
class sunNameLabel : sunNode
{
public sunIdentifier Label { get { return this[0] as sunIdentifier; } }
public sunNameLabel(sunSourceLocation location)
: base(location)
{
}
}
}

155
ast/nodes.system.cs Normal file
View file

@ -0,0 +1,155 @@
namespace arookas
{
class sunYield : sunNode
{
public sunYield(sunSourceLocation location)
: base(location)
{
}
public override void Compile(sunContext context)
{
var builtinInfo = context.ResolveSystemBuiltin("yield");
context.Text.CallBuiltin(builtinInfo.Index, 0);
context.Text.Pop();
}
}
class sunExit : sunNode
{
public sunExit(sunSourceLocation location)
: base(location)
{
}
public override void Compile(sunContext context)
{
var builtinInfo = context.ResolveSystemBuiltin("exit");
context.Text.CallBuiltin(builtinInfo.Index, 0);
context.Text.Pop();
}
}
class sunDump : sunNode
{
public sunDump(sunSourceLocation location)
: base(location)
{
}
public override void Compile(sunContext context)
{
var builtinInfo = context.ResolveSystemBuiltin("dump");
context.Text.CallBuiltin(builtinInfo.Index, 0);
context.Text.Pop();
}
}
class sunLock : sunNode
{
public sunLock(sunSourceLocation location)
: base(location)
{
}
public override void Compile(sunContext context)
{
var builtinInfo = context.ResolveSystemBuiltin("lock");
context.Text.CallBuiltin(builtinInfo.Index, 0);
context.Text.Pop();
}
}
class sunUnlock : sunNode
{
public sunUnlock(sunSourceLocation location)
: base(location)
{
}
public override void Compile(sunContext context)
{
var builtinInfo = context.ResolveSystemBuiltin("unlock");
context.Text.CallBuiltin(builtinInfo.Index, 0);
context.Text.Pop();
}
}
class sunIntCast : sunNode
{
public sunExpression Argument { get { return this[0] as sunExpression; } }
public sunIntCast(sunSourceLocation location)
: base(location)
{
}
public override void Compile(sunContext context)
{
var builtinInfo = context.DeclareSystemBuiltin("int", false, "x");
Argument.Compile(context);
context.Text.CallBuiltin(builtinInfo.Index, 1);
}
}
class sunFloatCast : sunNode
{
public sunExpression Argument { get { return this[0] as sunExpression; } }
public sunFloatCast(sunSourceLocation location)
: base(location)
{
}
public override void Compile(sunContext context)
{
var builtinInfo = context.ResolveSystemBuiltin("float");
Argument.Compile(context);
context.Text.CallBuiltin(builtinInfo.Index, 1);
}
}
class sunTypeofCast : sunNode
{
public sunExpression Argument { get { return this[0] as sunExpression; } }
public sunTypeofCast(sunSourceLocation location)
: base(location)
{
}
public override void Compile(sunContext context)
{
var builtinInfo = context.ResolveSystemBuiltin("typeof");
Argument.Compile(context);
context.Text.CallBuiltin(builtinInfo.Index, 1);
}
}
class sunPrint : sunNode
{
public sunNode ArgumentList { get { return this[0]; } }
public sunPrint(sunSourceLocation location)
: base(location)
{
}
public override void Compile(sunContext context)
{
var builtinInfo = context.ResolveSystemBuiltin("print");
ArgumentList.Compile(context);
context.Text.CallBuiltin(builtinInfo.Index, ArgumentList.Count);
context.Text.Pop();
}
}
}

96
ast/nodes.variables.cs Normal file
View file

@ -0,0 +1,96 @@
namespace arookas
{
class sunVariableReference : sunNode
{
public sunIdentifier Variable { get { return this[0] as sunIdentifier; } }
public sunVariableReference(sunSourceLocation location)
: base(location)
{
}
public override void Compile(sunContext context)
{
sunVariableInfo variableInfo;
sunConstInfo constInfo;
context.ResolveVariableOrConstant(Variable, out variableInfo, out constInfo);
if (variableInfo != null)
{
context.Text.PushVariable(variableInfo);
}
if (constInfo != null)
{
constInfo.Expression.Compile(context);
}
}
}
class sunVariableDeclaration : sunNode
{
public sunIdentifier Variable { get { return this[0] as sunIdentifier; } }
public sunVariableDeclaration(sunSourceLocation location)
: base(location)
{
}
public override void Compile(sunContext context)
{
var variableInfo = context.DeclareVariable(Variable);
context.Text.DeclareLocal(1);
}
}
class sunVariableDefinition : sunVariableAssignment
{
public sunVariableDefinition(sunSourceLocation location)
: base(location)
{
}
public override void Compile(sunContext context)
{
var variableInfo = context.DeclareVariable(Variable);
context.Text.DeclareLocal(1);
base.Compile(context);
}
}
class sunVariableAssignment : sunVariableDeclaration
{
public sunAssign Operator { get { return this[1] as sunAssign; } }
public sunExpression Expression { get { return this[2] as sunExpression; } }
public sunVariableAssignment(sunSourceLocation location)
: base(location)
{
}
public override void Compile(sunContext context)
{
var variableInfo = context.ResolveVariable(Variable);
Operator.Compile(context, variableInfo, Expression);
}
}
class sunConstDefinition : sunNode
{
public sunIdentifier Constant { get { return this[0] as sunIdentifier; } }
public sunExpression Expression { get { return this[2] as sunExpression; } }
public sunConstDefinition(sunSourceLocation location)
: base(location)
{
}
public override void Compile(sunContext context)
{
var constInfo = context.DeclareConstant(Constant, Expression);
}
}
}