Cleanup.
TIL I can set the automatic formatting of opening braces in VS. What have I been doing all this time??
This commit is contained in:
parent
f5394f56d0
commit
2f9b251fd8
19 changed files with 589 additions and 1332 deletions
|
@ -4,16 +4,13 @@ using System.Collections.Generic;
|
|||
|
||||
namespace arookas
|
||||
{
|
||||
public class sunSourceLocation
|
||||
{
|
||||
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)
|
||||
{
|
||||
if (file == null)
|
||||
{
|
||||
public sunSourceLocation(string file, int line, int column) {
|
||||
if (file == null) {
|
||||
throw new ArgumentNullException("file");
|
||||
}
|
||||
File = file;
|
||||
|
@ -21,14 +18,10 @@ namespace arookas
|
|||
Column = column;
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return String.Format("\"{0}\", ({1},{2})", File, Line, Column);
|
||||
}
|
||||
public override string ToString() { return String.Format("\"{0}\", ({1},{2})", File, Line, Column); }
|
||||
}
|
||||
|
||||
class sunNode : IEnumerable<sunNode>
|
||||
{
|
||||
class sunNode : IEnumerable<sunNode> {
|
||||
List<sunNode> mChildren;
|
||||
|
||||
public sunNode Parent { get; private set; }
|
||||
|
@ -41,27 +34,20 @@ namespace arookas
|
|||
public bool IsBranch { get { return Count > 0; } }
|
||||
public bool IsLeaf { get { return Count < 1; } }
|
||||
|
||||
public int MaxLocalCount
|
||||
{
|
||||
get
|
||||
{
|
||||
public int MaxLocalCount {
|
||||
get {
|
||||
int locals = 0;
|
||||
int maxChildLocals = 0;
|
||||
foreach (var child in this)
|
||||
{
|
||||
if (child is sunVariableDeclaration || child is sunVariableDefinition)
|
||||
{
|
||||
foreach (var child in this) {
|
||||
if (child is sunVariableDeclaration || child is sunVariableDefinition) {
|
||||
++locals;
|
||||
}
|
||||
else if (child is sunCompoundStatement)
|
||||
{
|
||||
else if (child is sunCompoundStatement) {
|
||||
locals += child.MaxLocalCount; // HACK: compound statements aren't their own scope
|
||||
}
|
||||
else if (!(child is sunFunctionDefinition)) // don't recurse into function bodies
|
||||
{
|
||||
else if (!(child is sunFunctionDefinition)) { // don't recurse into function bodies
|
||||
int childLocals = child.MaxLocalCount;
|
||||
if (childLocals > maxChildLocals)
|
||||
{
|
||||
if (childLocals > maxChildLocals) {
|
||||
maxChildLocals = childLocals;
|
||||
}
|
||||
}
|
||||
|
@ -70,60 +56,47 @@ namespace arookas
|
|||
}
|
||||
}
|
||||
|
||||
public sunNode(sunSourceLocation location)
|
||||
{
|
||||
public sunNode(sunSourceLocation location) {
|
||||
mChildren = new List<sunNode>(5);
|
||||
Location = location;
|
||||
}
|
||||
|
||||
public void Add(sunNode node)
|
||||
{
|
||||
if (node == null)
|
||||
{
|
||||
public void Add(sunNode node) {
|
||||
if (node == null) {
|
||||
throw new ArgumentNullException("node");
|
||||
}
|
||||
if (node.Parent != null)
|
||||
{
|
||||
if (node.Parent != null) {
|
||||
node.Parent.Remove(node);
|
||||
}
|
||||
node.Parent = this;
|
||||
mChildren.Add(node);
|
||||
}
|
||||
public void Remove(sunNode node)
|
||||
{
|
||||
if (node == null)
|
||||
{
|
||||
public void Remove(sunNode node) {
|
||||
if (node == null) {
|
||||
throw new ArgumentNullException("node");
|
||||
}
|
||||
if (node.Parent == this)
|
||||
{
|
||||
if (node.Parent == this) {
|
||||
mChildren.Remove(node);
|
||||
node.Parent = null;
|
||||
}
|
||||
}
|
||||
public void Clear()
|
||||
{
|
||||
foreach (var child in this)
|
||||
{
|
||||
public void Clear() {
|
||||
foreach (var child in this) {
|
||||
child.Parent = null;
|
||||
}
|
||||
mChildren.Clear();
|
||||
}
|
||||
|
||||
public virtual void Compile(sunContext context)
|
||||
{
|
||||
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)
|
||||
{
|
||||
foreach (var child in this) {
|
||||
child.Compile(context);
|
||||
}
|
||||
}
|
||||
protected bool TryCompile(sunNode node, sunContext context)
|
||||
{
|
||||
if (node != null)
|
||||
{
|
||||
protected bool TryCompile(sunNode node, sunContext context) {
|
||||
if (node != null) {
|
||||
node.Compile(context);
|
||||
return true;
|
||||
}
|
||||
|
@ -134,14 +107,10 @@ namespace arookas
|
|||
IEnumerator IEnumerable.GetEnumerator() { return GetEnumerator(); }
|
||||
}
|
||||
|
||||
abstract class sunToken<TValue> : sunNode
|
||||
{
|
||||
abstract class sunToken<TValue> : sunNode {
|
||||
public TValue Value { get; protected set; }
|
||||
|
||||
protected sunToken(sunSourceLocation location)
|
||||
: base(location)
|
||||
{
|
||||
|
||||
}
|
||||
: base(location) { }
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,114 +2,84 @@
|
|||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
||||
namespace arookas
|
||||
{
|
||||
class sunExpression : sunNode
|
||||
{
|
||||
namespace arookas {
|
||||
class sunExpression : sunNode {
|
||||
public sunExpression(sunSourceLocation location)
|
||||
: base(location)
|
||||
{
|
||||
: base(location) { }
|
||||
|
||||
}
|
||||
|
||||
public override void Compile(sunContext context)
|
||||
{
|
||||
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)
|
||||
{
|
||||
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)
|
||||
{
|
||||
foreach (var node in expression) {
|
||||
if (node is sunOperand) {
|
||||
var operand = node as sunOperand;
|
||||
|
||||
// term
|
||||
var term = operand.Term;
|
||||
if (term is sunExpression)
|
||||
{
|
||||
if (term is sunExpression) {
|
||||
AnalyzeExpression(context, term as sunExpression, operatorStack);
|
||||
}
|
||||
else
|
||||
{
|
||||
else {
|
||||
term.Compile(context);
|
||||
}
|
||||
var unaryOperators = operand.UnaryOperators;
|
||||
if (unaryOperators != null)
|
||||
{
|
||||
if (unaryOperators != null) {
|
||||
unaryOperators.Compile(context);
|
||||
}
|
||||
}
|
||||
else if (node is sunOperator)
|
||||
{
|
||||
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))
|
||||
{
|
||||
(operatorNode.IsRightAssociative && operatorNode.Precedence < operatorStack.Peek().Precedence)) {
|
||||
operatorStack.Pop().Compile(context);
|
||||
}
|
||||
operatorStack.Push(operatorNode);
|
||||
}
|
||||
}
|
||||
while (operatorStack.Count > stackCount)
|
||||
{
|
||||
while (operatorStack.Count > stackCount) {
|
||||
operatorStack.Pop().Compile(context);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class sunOperand : sunNode
|
||||
{
|
||||
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)
|
||||
{
|
||||
|
||||
}
|
||||
: base(location) { }
|
||||
|
||||
// operands are compiled in sunExpression.Compile
|
||||
}
|
||||
|
||||
class sunUnaryOperatorList : sunNode
|
||||
{
|
||||
class sunUnaryOperatorList : sunNode {
|
||||
public sunUnaryOperatorList(sunSourceLocation location)
|
||||
: base(location)
|
||||
{
|
||||
: base(location) { }
|
||||
|
||||
}
|
||||
|
||||
public override void Compile(sunContext context)
|
||||
{
|
||||
foreach (var child in this.Reverse())
|
||||
{
|
||||
public override void Compile(sunContext context) {
|
||||
foreach (var child in this.Reverse()) {
|
||||
// compile unary operators in reverse order
|
||||
child.Compile(context);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class sunTernaryOperator : sunNode
|
||||
{
|
||||
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 location)
|
||||
: base(location)
|
||||
{
|
||||
: base(location) { }
|
||||
|
||||
}
|
||||
|
||||
public override void Compile(sunContext context)
|
||||
{
|
||||
public override void Compile(sunContext context) {
|
||||
Condition.Compile(context);
|
||||
var falsePrologue = context.Text.GotoIfZero();
|
||||
TrueBody.Compile(context);
|
||||
|
@ -121,94 +91,66 @@ namespace arookas
|
|||
}
|
||||
|
||||
// increment/decrement
|
||||
class sunPostfixAugment : sunOperand
|
||||
{
|
||||
class sunPostfixAugment : sunOperand {
|
||||
public sunIdentifier Variable { get { return this[0] as sunIdentifier; } }
|
||||
public sunAugment Augment { get { return this[1] as sunAugment; } }
|
||||
|
||||
public sunPostfixAugment(sunSourceLocation location)
|
||||
: base(location)
|
||||
{
|
||||
: base(location) { }
|
||||
|
||||
}
|
||||
|
||||
public override void Compile(sunContext context)
|
||||
{
|
||||
public override void Compile(sunContext context) {
|
||||
var symbol = context.MustResolveStorable(Variable);
|
||||
if (symbol is sunConstantSymbol)
|
||||
{
|
||||
if (symbol is sunConstantSymbol) {
|
||||
throw new sunAssignConstantException(Variable);
|
||||
}
|
||||
if (Parent is sunOperand)
|
||||
{
|
||||
if (Parent is sunOperand) {
|
||||
symbol.CompileGet(context);
|
||||
}
|
||||
Augment.Compile(context, symbol);
|
||||
}
|
||||
}
|
||||
|
||||
class sunPrefixAugment : sunOperand
|
||||
{
|
||||
class sunPrefixAugment : sunOperand {
|
||||
public sunAugment Augment { get { return this[0] as sunAugment; } }
|
||||
public sunIdentifier Variable { get { return this[1] as sunIdentifier; } }
|
||||
|
||||
public sunPrefixAugment(sunSourceLocation location)
|
||||
: base(location)
|
||||
{
|
||||
: base(location) { }
|
||||
|
||||
}
|
||||
|
||||
public override void Compile(sunContext context)
|
||||
{
|
||||
public override void Compile(sunContext context) {
|
||||
var symbol = context.MustResolveStorable(Variable);
|
||||
if (symbol is sunConstantSymbol)
|
||||
{
|
||||
if (symbol is sunConstantSymbol) {
|
||||
throw new sunAssignConstantException(Variable);
|
||||
}
|
||||
Augment.Compile(context, symbol);
|
||||
if (Parent is sunOperand)
|
||||
{
|
||||
if (Parent is sunOperand) {
|
||||
symbol.CompileGet(context);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
abstract class sunAugment : sunNode
|
||||
{
|
||||
abstract class sunAugment : sunNode {
|
||||
protected sunAugment(sunSourceLocation location)
|
||||
: base(location)
|
||||
{
|
||||
|
||||
}
|
||||
: base(location) { }
|
||||
|
||||
public abstract void Compile(sunContext context, sunStorableSymbol symbol);
|
||||
}
|
||||
|
||||
class sunIncrement : sunAugment
|
||||
{
|
||||
class sunIncrement : sunAugment {
|
||||
public sunIncrement(sunSourceLocation location)
|
||||
: base(location)
|
||||
{
|
||||
: base(location) { }
|
||||
|
||||
}
|
||||
|
||||
public override void Compile(sunContext context, sunStorableSymbol symbol)
|
||||
{
|
||||
public override void Compile(sunContext context, sunStorableSymbol symbol) {
|
||||
symbol.CompileInc(context);
|
||||
symbol.CompileSet(context);
|
||||
}
|
||||
}
|
||||
|
||||
class sunDecrement : sunAugment
|
||||
{
|
||||
class sunDecrement : sunAugment {
|
||||
public sunDecrement(sunSourceLocation location)
|
||||
: base(location)
|
||||
{
|
||||
: base(location) { }
|
||||
|
||||
}
|
||||
|
||||
public override void Compile(sunContext context, sunStorableSymbol symbol)
|
||||
{
|
||||
public override void Compile(sunContext context, sunStorableSymbol symbol) {
|
||||
symbol.CompileDec(context);
|
||||
symbol.CompileSet(context);
|
||||
}
|
||||
|
|
|
@ -1,50 +1,38 @@
|
|||
using PerCederberg.Grammatica.Runtime;
|
||||
using System.Linq;
|
||||
|
||||
namespace arookas
|
||||
{
|
||||
class sunIf : sunNode
|
||||
{
|
||||
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)
|
||||
{
|
||||
: base(location) { }
|
||||
|
||||
}
|
||||
|
||||
public override void Compile(sunContext context)
|
||||
{
|
||||
public override void Compile(sunContext context) {
|
||||
Condition.Compile(context);
|
||||
var trueBodyEpilogue = context.Text.GotoIfZero();
|
||||
TrueBody.Compile(context);
|
||||
var falseBody = FalseBody;
|
||||
if (falseBody != null)
|
||||
{
|
||||
if (falseBody != null) {
|
||||
var falseBodyEpilogue = context.Text.Goto();
|
||||
context.Text.ClosePoint(trueBodyEpilogue);
|
||||
falseBody.Compile(context);
|
||||
context.Text.ClosePoint(falseBodyEpilogue);
|
||||
}
|
||||
else
|
||||
{
|
||||
else {
|
||||
context.Text.ClosePoint(trueBodyEpilogue);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
abstract class sunLoop : sunNode
|
||||
{
|
||||
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)
|
||||
{
|
||||
|
||||
}
|
||||
: base(location) { }
|
||||
}
|
||||
|
||||
class sunWhile : sunLoop
|
||||
|
@ -53,13 +41,9 @@ namespace arookas
|
|||
public sunNode Body { get { return this[Count - 1]; } }
|
||||
|
||||
public sunWhile(sunSourceLocation location)
|
||||
: base(location)
|
||||
{
|
||||
: base(location) { }
|
||||
|
||||
}
|
||||
|
||||
public override void Compile(sunContext context)
|
||||
{
|
||||
public override void Compile(sunContext context) {
|
||||
context.Loops.Push(IsNamed ? NameLabel.Label.Value : null);
|
||||
var bodyPrologue = context.Text.OpenPoint();
|
||||
var continuePoint = context.Text.OpenPoint();
|
||||
|
@ -79,13 +63,9 @@ namespace arookas
|
|||
public sunExpression Condition { get { return this[Count - 1] as sunExpression; } }
|
||||
|
||||
public sunDo(sunSourceLocation location)
|
||||
: base(location)
|
||||
{
|
||||
: base(location) { }
|
||||
|
||||
}
|
||||
|
||||
public override void Compile(sunContext context)
|
||||
{
|
||||
public override void Compile(sunContext context) {
|
||||
context.Loops.Push(IsNamed ? NameLabel.Label.Value : null);
|
||||
var bodyPrologue = context.Text.OpenPoint();
|
||||
Body.Compile(context);
|
||||
|
@ -99,21 +79,16 @@ namespace arookas
|
|||
}
|
||||
}
|
||||
|
||||
class sunFor : sunLoop
|
||||
{
|
||||
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)
|
||||
{
|
||||
: base(location) { }
|
||||
|
||||
}
|
||||
|
||||
public override void Compile(sunContext context)
|
||||
{
|
||||
public override void Compile(sunContext context) {
|
||||
context.Scopes.Push(context.Scopes.Top.Type);
|
||||
context.Loops.Push(IsNamed ? NameLabel.Label.Value : null);
|
||||
TryCompile(Declaration, context);
|
||||
|
@ -130,93 +105,62 @@ namespace arookas
|
|||
context.Scopes.Pop();
|
||||
}
|
||||
}
|
||||
class sunForDeclaration : sunNode
|
||||
{
|
||||
class sunForDeclaration : sunNode {
|
||||
public sunForDeclaration(sunSourceLocation location)
|
||||
: base(location)
|
||||
{
|
||||
|
||||
}
|
||||
: base(location) { }
|
||||
}
|
||||
class sunForCondition : sunNode
|
||||
{
|
||||
class sunForCondition : sunNode {
|
||||
public sunForCondition(sunSourceLocation location)
|
||||
: base(location)
|
||||
{
|
||||
|
||||
}
|
||||
: base(location) { }
|
||||
}
|
||||
class sunForIteration : sunNode
|
||||
{
|
||||
class sunForIteration : sunNode {
|
||||
public sunForIteration(sunSourceLocation location)
|
||||
: base(location)
|
||||
{
|
||||
|
||||
}
|
||||
: base(location) { }
|
||||
}
|
||||
|
||||
class sunReturn : sunNode
|
||||
{
|
||||
class sunReturn : sunNode {
|
||||
public sunExpression Expression { get { return this[0] as sunExpression; } }
|
||||
|
||||
public sunReturn(sunSourceLocation location)
|
||||
: base(location)
|
||||
{
|
||||
: base(location) { }
|
||||
|
||||
}
|
||||
|
||||
public override void Compile(sunContext context)
|
||||
{
|
||||
public override void Compile(sunContext context) {
|
||||
var expression = Expression;
|
||||
if (expression != null)
|
||||
{
|
||||
if (expression != null) {
|
||||
expression.Compile(context);
|
||||
context.Text.ReturnValue();
|
||||
}
|
||||
else
|
||||
{
|
||||
else {
|
||||
context.Text.ReturnVoid();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class sunBreak : sunNode
|
||||
{
|
||||
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)
|
||||
{
|
||||
: base(location) { }
|
||||
|
||||
}
|
||||
|
||||
public override void Compile(sunContext context)
|
||||
{
|
||||
public override void Compile(sunContext context) {
|
||||
var point = context.Text.Goto();
|
||||
if (!context.Loops.AddBreak(point, IsNamed ? NameLabel.Value : null))
|
||||
{
|
||||
if (!context.Loops.AddBreak(point, IsNamed ? NameLabel.Value : null)) {
|
||||
throw new sunBreakException(this);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class sunContinue : sunNode
|
||||
{
|
||||
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)
|
||||
{
|
||||
: base(location) { }
|
||||
|
||||
}
|
||||
|
||||
public override void Compile(sunContext context)
|
||||
{
|
||||
public override void Compile(sunContext context) {
|
||||
var point = context.Text.Goto();
|
||||
if (!context.Loops.AddContinue(point, IsNamed ? NameLabel.Value : null))
|
||||
{
|
||||
if (!context.Loops.AddContinue(point, IsNamed ? NameLabel.Value : null)) {
|
||||
throw new sunContinueException(this);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,95 +1,70 @@
|
|||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
||||
namespace arookas
|
||||
{
|
||||
class sunBuiltinDeclaration : sunNode
|
||||
{
|
||||
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)
|
||||
{
|
||||
: base(location) { }
|
||||
|
||||
}
|
||||
|
||||
public override void Compile(sunContext context)
|
||||
{
|
||||
public override void Compile(sunContext context) {
|
||||
context.DeclareBuiltin(this);
|
||||
}
|
||||
}
|
||||
|
||||
class sunFunctionDefinition : sunNode
|
||||
{
|
||||
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)
|
||||
{
|
||||
: base(location) { }
|
||||
|
||||
}
|
||||
|
||||
public override void Compile(sunContext context)
|
||||
{
|
||||
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
|
||||
{
|
||||
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)
|
||||
{
|
||||
: base(location) { }
|
||||
|
||||
}
|
||||
|
||||
public override void Compile(sunContext context)
|
||||
{
|
||||
public override void Compile(sunContext context) {
|
||||
var callableInfo = context.MustResolveCallable(this);
|
||||
if (!callableInfo.Parameters.ValidateArgumentCount(Arguments.Count))
|
||||
{
|
||||
if (!callableInfo.Parameters.ValidateArgumentCount(Arguments.Count)) {
|
||||
throw new sunArgumentCountException(this, callableInfo);
|
||||
}
|
||||
Arguments.Compile(context);
|
||||
callableInfo.OpenCallSite(context, Arguments.Count);
|
||||
if (IsStatement)
|
||||
{
|
||||
if (IsStatement) {
|
||||
context.Text.Pop();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class sunParameterList : sunNode
|
||||
{
|
||||
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)
|
||||
{
|
||||
: base(location) {
|
||||
int count = this.Count(i => i is sunEllipsis);
|
||||
if (count > 1 || (count > 0 && !(this[Count - 1] is sunEllipsis)))
|
||||
{
|
||||
if (count > 1 || (count > 0 && !(this[Count - 1] is sunEllipsis))) {
|
||||
throw new sunVariadicParameterListException(this);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class sunEllipsis : sunNode
|
||||
{
|
||||
class sunEllipsis : sunNode {
|
||||
public sunEllipsis(sunSourceLocation location)
|
||||
: base(location)
|
||||
{
|
||||
|
||||
}
|
||||
: base(location) { }
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,91 +2,70 @@
|
|||
using System.Globalization;
|
||||
using System.Text;
|
||||
|
||||
namespace arookas
|
||||
{
|
||||
class sunIntLiteral : sunToken<int> // base-10 integer
|
||||
{
|
||||
namespace arookas {
|
||||
class sunIntLiteral : sunToken<int> { // base-10 integer
|
||||
public sunIntLiteral(sunSourceLocation location, string literal)
|
||||
: base(location)
|
||||
{
|
||||
: base(location) {
|
||||
Value = Int32.Parse(literal);
|
||||
}
|
||||
protected sunIntLiteral(sunSourceLocation location)
|
||||
: base(location)
|
||||
{
|
||||
// this overload lets protected classes set the value to something else
|
||||
}
|
||||
|
||||
public override void Compile(sunContext context)
|
||||
{
|
||||
context.Text.PushInt(Value);
|
||||
}
|
||||
// this overload lets protected classes set the value to something else
|
||||
protected sunIntLiteral(sunSourceLocation location)
|
||||
: base(location) { }
|
||||
|
||||
public override void Compile(sunContext context) { context.Text.PushInt(Value); }
|
||||
}
|
||||
|
||||
class sunHexLiteral : sunIntLiteral // base-16 integer
|
||||
{
|
||||
class sunHexLiteral : sunIntLiteral { // base-16 integer
|
||||
public sunHexLiteral(sunSourceLocation location, string literal)
|
||||
: base(location)
|
||||
{
|
||||
: base(location) {
|
||||
// because .NET's hex parsing is gay and doesn't support
|
||||
// leading signs, manually detect negative literals
|
||||
var neg = (literal[0] == '-');
|
||||
var trim = neg ? 3 : 2;
|
||||
var digits = literal.Substring(trim); // trim the '0x' prefix before parsing
|
||||
Value = Int32.Parse(literal.Substring(2), NumberStyles.AllowHexSpecifier);
|
||||
if (neg)
|
||||
{
|
||||
if (neg) {
|
||||
Value = -Value;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class sunFloatLiteral : sunToken<float>
|
||||
{
|
||||
class sunFloatLiteral : sunToken<float> {
|
||||
public sunFloatLiteral(sunSourceLocation location, string literal)
|
||||
: base(location)
|
||||
{
|
||||
: base(location) {
|
||||
Value = Single.Parse(literal);
|
||||
}
|
||||
|
||||
public override void Compile(sunContext context)
|
||||
{
|
||||
public override void Compile(sunContext context) {
|
||||
context.Text.PushFloat(Value);
|
||||
}
|
||||
}
|
||||
|
||||
class sunStringLiteral : sunToken<string>
|
||||
{
|
||||
class sunStringLiteral : sunToken<string> {
|
||||
public sunStringLiteral(sunSourceLocation location, string literal)
|
||||
: base(location)
|
||||
{
|
||||
: base(location) {
|
||||
Value = UnescapeString(literal.Substring(1, literal.Length - 2)); // remove enclosing quotes
|
||||
}
|
||||
|
||||
public override void Compile(sunContext context)
|
||||
{
|
||||
public override void Compile(sunContext context) {
|
||||
context.Text.PushData(context.DataTable.Add(Value));
|
||||
}
|
||||
|
||||
// string unescaping utility
|
||||
string UnescapeString(string value)
|
||||
{
|
||||
string UnescapeString(string value) {
|
||||
// based on Hans Passant's code
|
||||
StringBuilder sb = new StringBuilder(value.Length);
|
||||
for (int i = 0; i < value.Length;)
|
||||
{
|
||||
for (int i = 0; i < value.Length;) {
|
||||
int j = value.IndexOf('\\', i);
|
||||
if (j < 0 || j >= value.Length - 1)
|
||||
{
|
||||
if (j < 0 || j >= value.Length - 1) {
|
||||
j = value.Length;
|
||||
}
|
||||
sb.Append(value, i, j - i);
|
||||
if (j >= value.Length)
|
||||
{
|
||||
if (j >= value.Length) {
|
||||
break;
|
||||
}
|
||||
switch (value[j + 1])
|
||||
{
|
||||
switch (value[j + 1]) {
|
||||
case '\'': sb.Append('\''); break;
|
||||
case '"': sb.Append('"'); break;
|
||||
case '\\': sb.Append('\\'); break;
|
||||
|
@ -106,16 +85,13 @@ namespace arookas
|
|||
}
|
||||
return sb.ToString();
|
||||
}
|
||||
char UnescapeHex(string value, int start, out int end)
|
||||
{
|
||||
if (start > value.Length)
|
||||
{
|
||||
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]))
|
||||
{
|
||||
while (digits < 4 && start < value.Length && IsHexDigit(value[start])) {
|
||||
sb.Append(value[start]);
|
||||
++digits;
|
||||
++start;
|
||||
|
@ -123,46 +99,37 @@ namespace arookas
|
|||
end = start;
|
||||
return (char)Int32.Parse(sb.ToString(), NumberStyles.AllowHexSpecifier);
|
||||
}
|
||||
char UnescapeUnicodeCodeUnit(string value, int start, out int end)
|
||||
{
|
||||
if (start >= value.Length - 4)
|
||||
{
|
||||
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)
|
||||
{
|
||||
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))
|
||||
{
|
||||
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)
|
||||
{
|
||||
static bool IsHexDigit(char c) {
|
||||
return (c >= '0' && c <= '9') ||
|
||||
(c >= 'A' && c <= 'F') ||
|
||||
(c >= 'a' && c <= 'f');
|
||||
}
|
||||
}
|
||||
|
||||
class sunIdentifier : sunToken<string>
|
||||
{
|
||||
class sunIdentifier : sunToken<string> {
|
||||
public sunIdentifier(sunSourceLocation location, string identifier)
|
||||
: base(location)
|
||||
{
|
||||
: base(location) {
|
||||
// make sure it is a valid identifier name (i.e. not a keyword)
|
||||
if (sunParser.IsKeyword(identifier))
|
||||
{
|
||||
if (sunParser.IsKeyword(identifier)) {
|
||||
throw new sunIdentifierException(this);
|
||||
}
|
||||
Value = identifier;
|
||||
|
@ -171,20 +138,16 @@ namespace arookas
|
|||
// identifiers are compiled on a per-context basis (i.e. at a higher level)
|
||||
}
|
||||
|
||||
class sunTrue : sunIntLiteral
|
||||
{
|
||||
class sunTrue : sunIntLiteral {
|
||||
public sunTrue(sunSourceLocation location)
|
||||
: base(location)
|
||||
{
|
||||
: base(location) {
|
||||
Value = 1;
|
||||
}
|
||||
}
|
||||
|
||||
class sunFalse : sunIntLiteral
|
||||
{
|
||||
class sunFalse : sunIntLiteral {
|
||||
public sunFalse(sunSourceLocation location)
|
||||
: base(location)
|
||||
{
|
||||
: base(location) {
|
||||
Value = 0;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,15 +1,12 @@
|
|||
using PerCederberg.Grammatica.Runtime;
|
||||
|
||||
namespace arookas
|
||||
{
|
||||
enum Associativity
|
||||
{
|
||||
namespace arookas {
|
||||
enum Associativity {
|
||||
Left,
|
||||
Right,
|
||||
}
|
||||
|
||||
abstract class sunOperator : sunNode
|
||||
{
|
||||
abstract class sunOperator : sunNode {
|
||||
public virtual Associativity Associativity { get { return Associativity.Left; } }
|
||||
public abstract int Precedence { get; }
|
||||
|
||||
|
@ -17,297 +14,208 @@ namespace arookas
|
|||
public bool IsRightAssociative { get { return Associativity == Associativity.Right; } }
|
||||
|
||||
protected sunOperator(sunSourceLocation location)
|
||||
: base(location)
|
||||
{
|
||||
|
||||
}
|
||||
: base(location) { }
|
||||
}
|
||||
|
||||
// precedence 0
|
||||
class sunLogOR : sunOperator
|
||||
{
|
||||
class sunLogOR : sunOperator {
|
||||
public override int Precedence { get { return 0; } }
|
||||
|
||||
public sunLogOR(sunSourceLocation location)
|
||||
: base(location)
|
||||
{
|
||||
|
||||
}
|
||||
: base(location) { }
|
||||
|
||||
public override void Compile(sunContext context) { context.Text.LogOR(); }
|
||||
}
|
||||
|
||||
// precedence 1
|
||||
class sunLogAND : sunOperator
|
||||
{
|
||||
class sunLogAND : sunOperator {
|
||||
public override int Precedence { get { return 1; } }
|
||||
|
||||
public sunLogAND(sunSourceLocation location)
|
||||
: base(location)
|
||||
{
|
||||
|
||||
}
|
||||
: base(location) { }
|
||||
|
||||
public override void Compile(sunContext context) { context.Text.LogAND(); }
|
||||
}
|
||||
|
||||
// precedence 2
|
||||
class sunBitOR : sunOperator
|
||||
{
|
||||
class sunBitOR : sunOperator {
|
||||
public override int Precedence { get { return 2; } }
|
||||
|
||||
public sunBitOR(sunSourceLocation location)
|
||||
: base(location)
|
||||
{
|
||||
|
||||
}
|
||||
: base(location) { }
|
||||
|
||||
public override void Compile(sunContext context) { context.Text.BitOR(); }
|
||||
}
|
||||
|
||||
// precedence 3
|
||||
class sunBitAND : sunOperator
|
||||
{
|
||||
class sunBitAND : sunOperator {
|
||||
public override int Precedence { get { return 3; } }
|
||||
|
||||
public sunBitAND(sunSourceLocation location)
|
||||
: base(location)
|
||||
{
|
||||
|
||||
}
|
||||
: base(location) { }
|
||||
|
||||
public override void Compile(sunContext context) { context.Text.BitAND(); }
|
||||
}
|
||||
|
||||
// precedence 4
|
||||
class sunEq : sunOperator
|
||||
{
|
||||
class sunEq : sunOperator {
|
||||
public override int Precedence { get { return 4; } }
|
||||
|
||||
public sunEq(sunSourceLocation location)
|
||||
: base(location)
|
||||
{
|
||||
|
||||
}
|
||||
: base(location) { }
|
||||
|
||||
public override void Compile(sunContext context) { context.Text.Eq(); }
|
||||
}
|
||||
|
||||
class sunNtEq : sunOperator
|
||||
{
|
||||
class sunNtEq : sunOperator {
|
||||
public override int Precedence { get { return 4; } }
|
||||
|
||||
public sunNtEq(sunSourceLocation location)
|
||||
: base(location)
|
||||
{
|
||||
|
||||
}
|
||||
: base(location) { }
|
||||
|
||||
public override void Compile(sunContext context) { context.Text.NtEq(); }
|
||||
}
|
||||
|
||||
// precedence 5
|
||||
class sunLt : sunOperator
|
||||
{
|
||||
class sunLt : sunOperator {
|
||||
public override int Precedence { get { return 5; } }
|
||||
|
||||
public sunLt(sunSourceLocation location)
|
||||
: base(location)
|
||||
{
|
||||
|
||||
}
|
||||
: base(location) { }
|
||||
|
||||
public override void Compile(sunContext context) { context.Text.Lt(); }
|
||||
}
|
||||
|
||||
class sunLtEq : sunOperator
|
||||
{
|
||||
class sunLtEq : sunOperator {
|
||||
public override int Precedence { get { return 5; } }
|
||||
|
||||
public sunLtEq(sunSourceLocation location)
|
||||
: base(location)
|
||||
{
|
||||
|
||||
}
|
||||
: base(location) { }
|
||||
|
||||
public override void Compile(sunContext context) { context.Text.LtEq(); }
|
||||
}
|
||||
|
||||
class sunGt : sunOperator
|
||||
{
|
||||
class sunGt : sunOperator {
|
||||
public override int Precedence { get { return 5; } }
|
||||
|
||||
public sunGt(sunSourceLocation location)
|
||||
: base(location)
|
||||
{
|
||||
|
||||
}
|
||||
: base(location) { }
|
||||
|
||||
public override void Compile(sunContext context) { context.Text.Gt(); }
|
||||
}
|
||||
|
||||
class sunGtEq : sunOperator
|
||||
{
|
||||
class sunGtEq : sunOperator {
|
||||
public override int Precedence { get { return 5; } }
|
||||
|
||||
public sunGtEq(sunSourceLocation location)
|
||||
: base(location)
|
||||
{
|
||||
|
||||
}
|
||||
: base(location) { }
|
||||
|
||||
public override void Compile(sunContext context) { context.Text.GtEq(); }
|
||||
}
|
||||
|
||||
// precedence 6
|
||||
class sunBitLsh : sunOperator
|
||||
{
|
||||
class sunBitLsh : sunOperator {
|
||||
public override int Precedence { get { return 6; } }
|
||||
|
||||
public sunBitLsh(sunSourceLocation location)
|
||||
: base(location)
|
||||
{
|
||||
|
||||
}
|
||||
: base(location) { }
|
||||
|
||||
public override void Compile(sunContext context) { context.Text.ShL(); }
|
||||
}
|
||||
|
||||
class sunBitRsh : sunOperator
|
||||
{
|
||||
class sunBitRsh : sunOperator {
|
||||
public override int Precedence { get { return 6; } }
|
||||
|
||||
public sunBitRsh(sunSourceLocation location)
|
||||
: base(location)
|
||||
{
|
||||
|
||||
}
|
||||
: base(location) { }
|
||||
|
||||
public override void Compile(sunContext context) { context.Text.ShR(); }
|
||||
}
|
||||
|
||||
// precedence 7
|
||||
class sunAdd : sunOperator
|
||||
{
|
||||
class sunAdd : sunOperator {
|
||||
public override int Precedence { get { return 7; } }
|
||||
|
||||
public sunAdd(sunSourceLocation location)
|
||||
: base(location)
|
||||
{
|
||||
|
||||
}
|
||||
: base(location) { }
|
||||
|
||||
public override void Compile(sunContext context) { context.Text.Add(); }
|
||||
}
|
||||
|
||||
class sunSub : sunOperator
|
||||
{
|
||||
class sunSub : sunOperator {
|
||||
public override int Precedence { get { return 7; } }
|
||||
|
||||
public sunSub(sunSourceLocation location)
|
||||
: base(location)
|
||||
{
|
||||
|
||||
}
|
||||
: base(location) { }
|
||||
|
||||
public override void Compile(sunContext context) { context.Text.Sub(); }
|
||||
}
|
||||
|
||||
// precedence 8
|
||||
class sunMul : sunOperator
|
||||
{
|
||||
class sunMul : sunOperator {
|
||||
public override int Precedence { get { return 8; } }
|
||||
|
||||
public sunMul(sunSourceLocation location)
|
||||
: base(location)
|
||||
{
|
||||
|
||||
}
|
||||
: base(location) { }
|
||||
|
||||
public override void Compile(sunContext context) { context.Text.Mul(); }
|
||||
}
|
||||
|
||||
class sunDiv : sunOperator
|
||||
{
|
||||
class sunDiv : sunOperator {
|
||||
public override int Precedence { get { return 8; } }
|
||||
|
||||
public sunDiv(sunSourceLocation location)
|
||||
: base(location)
|
||||
{
|
||||
|
||||
}
|
||||
: base(location) { }
|
||||
|
||||
public override void Compile(sunContext context) { context.Text.Div(); }
|
||||
}
|
||||
|
||||
class sunMod : sunOperator
|
||||
{
|
||||
class sunMod : sunOperator {
|
||||
public override int Precedence { get { return 8; } }
|
||||
|
||||
public sunMod(sunSourceLocation location)
|
||||
: base(location)
|
||||
{
|
||||
|
||||
}
|
||||
: base(location) { }
|
||||
|
||||
public override void Compile(sunContext context) { context.Text.Mod(); }
|
||||
}
|
||||
|
||||
// precedence 9
|
||||
class sunLogNOT : sunOperator
|
||||
{
|
||||
class sunLogNOT : sunOperator {
|
||||
public override int Precedence { get { return 9; } }
|
||||
|
||||
public sunLogNOT(sunSourceLocation location)
|
||||
: base(location)
|
||||
{
|
||||
|
||||
}
|
||||
: base(location) { }
|
||||
|
||||
public override void Compile(sunContext context) { context.Text.LogNOT(); }
|
||||
}
|
||||
class sunNeg : sunOperator
|
||||
{
|
||||
class sunNeg : sunOperator {
|
||||
public override int Precedence { get { return 9; } }
|
||||
|
||||
public sunNeg(sunSourceLocation location)
|
||||
: base(location)
|
||||
{
|
||||
|
||||
}
|
||||
: base(location) { }
|
||||
|
||||
public override void Compile(sunContext context) { context.Text.Neg(); }
|
||||
}
|
||||
|
||||
// assignment operators
|
||||
class sunAssign : sunOperator
|
||||
{
|
||||
class sunAssign : sunOperator {
|
||||
public override Associativity Associativity { get { return Associativity.Right; } }
|
||||
public override int Precedence { get { return -1; } }
|
||||
|
||||
public sunAssign(sunSourceLocation location)
|
||||
: base(location)
|
||||
{
|
||||
: base(location) { }
|
||||
|
||||
}
|
||||
|
||||
public virtual void Compile(sunContext context, sunStorableSymbol symbol, sunExpression expression)
|
||||
{
|
||||
public virtual void Compile(sunContext context, sunStorableSymbol symbol, sunExpression expression) {
|
||||
expression.Compile(context);
|
||||
symbol.CompileSet(context);
|
||||
}
|
||||
}
|
||||
|
||||
class sunAssignAdd : sunAssign
|
||||
{
|
||||
class sunAssignAdd : sunAssign {
|
||||
public sunAssignAdd(sunSourceLocation location)
|
||||
: base(location)
|
||||
{
|
||||
: base(location) { }
|
||||
|
||||
}
|
||||
|
||||
public override void Compile(sunContext context, sunStorableSymbol symbol, sunExpression expression)
|
||||
{
|
||||
public override void Compile(sunContext context, sunStorableSymbol symbol, sunExpression expression) {
|
||||
symbol.CompileGet(context);
|
||||
expression.Compile(context);
|
||||
context.Text.Add();
|
||||
|
@ -315,16 +223,11 @@ namespace arookas
|
|||
}
|
||||
}
|
||||
|
||||
class sunAssignSub : sunAssign
|
||||
{
|
||||
class sunAssignSub : sunAssign {
|
||||
public sunAssignSub(sunSourceLocation location)
|
||||
: base(location)
|
||||
{
|
||||
: base(location) { }
|
||||
|
||||
}
|
||||
|
||||
public override void Compile(sunContext context, sunStorableSymbol symbol, sunExpression expression)
|
||||
{
|
||||
public override void Compile(sunContext context, sunStorableSymbol symbol, sunExpression expression) {
|
||||
symbol.CompileGet(context);
|
||||
expression.Compile(context);
|
||||
context.Text.Sub();
|
||||
|
@ -332,16 +235,11 @@ namespace arookas
|
|||
}
|
||||
}
|
||||
|
||||
class sunAssignMul : sunAssign
|
||||
{
|
||||
class sunAssignMul : sunAssign {
|
||||
public sunAssignMul(sunSourceLocation location)
|
||||
: base(location)
|
||||
{
|
||||
: base(location) { }
|
||||
|
||||
}
|
||||
|
||||
public override void Compile(sunContext context, sunStorableSymbol symbol, sunExpression expression)
|
||||
{
|
||||
public override void Compile(sunContext context, sunStorableSymbol symbol, sunExpression expression) {
|
||||
symbol.CompileGet(context);
|
||||
expression.Compile(context);
|
||||
context.Text.Mul();
|
||||
|
@ -349,16 +247,11 @@ namespace arookas
|
|||
}
|
||||
}
|
||||
|
||||
class sunAssignDiv : sunAssign
|
||||
{
|
||||
class sunAssignDiv : sunAssign {
|
||||
public sunAssignDiv(sunSourceLocation location)
|
||||
: base(location)
|
||||
{
|
||||
: base(location) { }
|
||||
|
||||
}
|
||||
|
||||
public override void Compile(sunContext context, sunStorableSymbol symbol, sunExpression expression)
|
||||
{
|
||||
public override void Compile(sunContext context, sunStorableSymbol symbol, sunExpression expression) {
|
||||
symbol.CompileGet(context);
|
||||
expression.Compile(context);
|
||||
context.Text.Div();
|
||||
|
@ -366,16 +259,11 @@ namespace arookas
|
|||
}
|
||||
}
|
||||
|
||||
class sunAssignMod : sunAssign
|
||||
{
|
||||
class sunAssignMod : sunAssign {
|
||||
public sunAssignMod(sunSourceLocation location)
|
||||
: base(location)
|
||||
{
|
||||
: base(location) { }
|
||||
|
||||
}
|
||||
|
||||
public override void Compile(sunContext context, sunStorableSymbol symbol, sunExpression expression)
|
||||
{
|
||||
public override void Compile(sunContext context, sunStorableSymbol symbol, sunExpression expression) {
|
||||
symbol.CompileGet(context);
|
||||
expression.Compile(context);
|
||||
context.Text.Mod();
|
||||
|
@ -383,16 +271,11 @@ namespace arookas
|
|||
}
|
||||
}
|
||||
|
||||
class sunAssignBitAND : sunAssign
|
||||
{
|
||||
class sunAssignBitAND : sunAssign {
|
||||
public sunAssignBitAND(sunSourceLocation location)
|
||||
: base(location)
|
||||
{
|
||||
: base(location) { }
|
||||
|
||||
}
|
||||
|
||||
public override void Compile(sunContext context, sunStorableSymbol symbol, sunExpression expression)
|
||||
{
|
||||
public override void Compile(sunContext context, sunStorableSymbol symbol, sunExpression expression) {
|
||||
symbol.CompileGet(context);
|
||||
expression.Compile(context);
|
||||
context.Text.BitAND();
|
||||
|
@ -400,16 +283,11 @@ namespace arookas
|
|||
}
|
||||
}
|
||||
|
||||
class sunAssignBitOR : sunAssign
|
||||
{
|
||||
class sunAssignBitOR : sunAssign {
|
||||
public sunAssignBitOR(sunSourceLocation location)
|
||||
: base(location)
|
||||
{
|
||||
: base(location) { }
|
||||
|
||||
}
|
||||
|
||||
public override void Compile(sunContext context, sunStorableSymbol symbol, sunExpression expression)
|
||||
{
|
||||
public override void Compile(sunContext context, sunStorableSymbol symbol, sunExpression expression) {
|
||||
symbol.CompileGet(context);
|
||||
expression.Compile(context);
|
||||
context.Text.BitOR();
|
||||
|
@ -417,16 +295,11 @@ namespace arookas
|
|||
}
|
||||
}
|
||||
|
||||
class sunAssignBitLsh : sunAssign
|
||||
{
|
||||
class sunAssignBitLsh : sunAssign {
|
||||
public sunAssignBitLsh(sunSourceLocation location)
|
||||
: base(location)
|
||||
{
|
||||
: base(location) { }
|
||||
|
||||
}
|
||||
|
||||
public override void Compile(sunContext context, sunStorableSymbol symbol, sunExpression expression)
|
||||
{
|
||||
public override void Compile(sunContext context, sunStorableSymbol symbol, sunExpression expression) {
|
||||
symbol.CompileGet(context);
|
||||
expression.Compile(context);
|
||||
context.Text.ShL();
|
||||
|
@ -434,16 +307,11 @@ namespace arookas
|
|||
}
|
||||
}
|
||||
|
||||
class sunAssignBitRsh : sunAssign
|
||||
{
|
||||
class sunAssignBitRsh : sunAssign {
|
||||
public sunAssignBitRsh(sunSourceLocation location)
|
||||
: base(location)
|
||||
{
|
||||
: base(location) { }
|
||||
|
||||
}
|
||||
|
||||
public override void Compile(sunContext context, sunStorableSymbol symbol, sunExpression expression)
|
||||
{
|
||||
public override void Compile(sunContext context, sunStorableSymbol symbol, sunExpression expression) {
|
||||
symbol.CompileGet(context);
|
||||
expression.Compile(context);
|
||||
context.Text.ShR();
|
||||
|
|
|
@ -1,59 +1,39 @@
|
|||
namespace arookas
|
||||
{
|
||||
class sunCompoundStatement : sunNode
|
||||
{
|
||||
namespace arookas {
|
||||
class sunCompoundStatement : sunNode {
|
||||
public sunCompoundStatement(sunSourceLocation location)
|
||||
: base(location)
|
||||
{
|
||||
|
||||
}
|
||||
: base(location) { }
|
||||
}
|
||||
|
||||
class sunStatementBlock : sunNode
|
||||
{
|
||||
class sunStatementBlock : sunNode {
|
||||
public sunStatementBlock(sunSourceLocation location)
|
||||
: base(location)
|
||||
{
|
||||
: base(location) { }
|
||||
|
||||
}
|
||||
|
||||
public override void Compile(sunContext context)
|
||||
{
|
||||
public override void Compile(sunContext context) {
|
||||
context.Scopes.Push(context.Scopes.Top.Type);
|
||||
base.Compile(context);
|
||||
context.Scopes.Pop();
|
||||
}
|
||||
}
|
||||
|
||||
class sunImport : sunNode
|
||||
{
|
||||
class sunImport : sunNode {
|
||||
public sunStringLiteral ImportFile { get { return this[0] as sunStringLiteral; } }
|
||||
|
||||
public sunImport(sunSourceLocation location)
|
||||
: base(location)
|
||||
{
|
||||
: base(location) { }
|
||||
|
||||
}
|
||||
|
||||
public override void Compile(sunContext context)
|
||||
{
|
||||
public override void Compile(sunContext context) {
|
||||
var result = context.Import(ImportFile.Value);
|
||||
switch (result)
|
||||
{
|
||||
switch (result) {
|
||||
case sunImportResult.Missing:
|
||||
case sunImportResult.FailedToLoad: throw new sunMissingImportException(this);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class sunNameLabel : sunNode
|
||||
{
|
||||
class sunNameLabel : sunNode {
|
||||
public sunIdentifier Label { get { return this[0] as sunIdentifier; } }
|
||||
|
||||
public sunNameLabel(sunSourceLocation location)
|
||||
: base(location)
|
||||
{
|
||||
|
||||
}
|
||||
: base(location) { }
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,151 +1,105 @@
|
|||
namespace arookas
|
||||
{
|
||||
class sunYield : sunNode
|
||||
{
|
||||
namespace arookas {
|
||||
class sunYield : sunNode {
|
||||
public sunYield(sunSourceLocation location)
|
||||
: base(location)
|
||||
{
|
||||
: base(location) { }
|
||||
|
||||
}
|
||||
|
||||
public override void Compile(sunContext context)
|
||||
{
|
||||
public override void Compile(sunContext context) {
|
||||
var builtinInfo = context.ResolveSystemBuiltin("yield");
|
||||
context.Text.CallBuiltin(builtinInfo.Index, 0);
|
||||
context.Text.Pop();
|
||||
}
|
||||
}
|
||||
|
||||
class sunExit : sunNode
|
||||
{
|
||||
class sunExit : sunNode {
|
||||
public sunExit(sunSourceLocation location)
|
||||
: base(location)
|
||||
{
|
||||
: base(location) { }
|
||||
|
||||
}
|
||||
|
||||
public override void Compile(sunContext context)
|
||||
{
|
||||
public override void Compile(sunContext context) {
|
||||
var builtinInfo = context.ResolveSystemBuiltin("exit");
|
||||
context.Text.CallBuiltin(builtinInfo.Index, 0);
|
||||
context.Text.Pop();
|
||||
}
|
||||
}
|
||||
|
||||
class sunDump : sunNode
|
||||
{
|
||||
class sunDump : sunNode {
|
||||
public sunDump(sunSourceLocation location)
|
||||
: base(location)
|
||||
{
|
||||
: base(location) { }
|
||||
|
||||
}
|
||||
|
||||
public override void Compile(sunContext context)
|
||||
{
|
||||
public override void Compile(sunContext context) {
|
||||
var builtinInfo = context.ResolveSystemBuiltin("dump");
|
||||
context.Text.CallBuiltin(builtinInfo.Index, 0);
|
||||
context.Text.Pop();
|
||||
}
|
||||
}
|
||||
|
||||
class sunLock : sunNode
|
||||
{
|
||||
class sunLock : sunNode {
|
||||
public sunLock(sunSourceLocation location)
|
||||
: base(location)
|
||||
{
|
||||
: base(location) { }
|
||||
|
||||
}
|
||||
|
||||
public override void Compile(sunContext context)
|
||||
{
|
||||
public override void Compile(sunContext context) {
|
||||
var builtinInfo = context.ResolveSystemBuiltin("lock");
|
||||
context.Text.CallBuiltin(builtinInfo.Index, 0);
|
||||
context.Text.Pop();
|
||||
}
|
||||
}
|
||||
|
||||
class sunUnlock : sunNode
|
||||
{
|
||||
class sunUnlock : sunNode {
|
||||
public sunUnlock(sunSourceLocation location)
|
||||
: base(location)
|
||||
{
|
||||
: base(location) { }
|
||||
|
||||
}
|
||||
|
||||
public override void Compile(sunContext context)
|
||||
{
|
||||
public override void Compile(sunContext context) {
|
||||
var builtinInfo = context.ResolveSystemBuiltin("unlock");
|
||||
context.Text.CallBuiltin(builtinInfo.Index, 0);
|
||||
context.Text.Pop();
|
||||
}
|
||||
}
|
||||
|
||||
class sunIntCast : sunNode
|
||||
{
|
||||
class sunIntCast : sunNode {
|
||||
public sunExpression Argument { get { return this[0] as sunExpression; } }
|
||||
|
||||
public sunIntCast(sunSourceLocation location)
|
||||
: base(location)
|
||||
{
|
||||
: base(location) { }
|
||||
|
||||
}
|
||||
|
||||
public override void Compile(sunContext context)
|
||||
{
|
||||
public override void Compile(sunContext context) {
|
||||
var builtinInfo = context.ResolveSystemBuiltin("int");
|
||||
Argument.Compile(context);
|
||||
context.Text.CallBuiltin(builtinInfo.Index, 1);
|
||||
}
|
||||
}
|
||||
|
||||
class sunFloatCast : sunNode
|
||||
{
|
||||
class sunFloatCast : sunNode {
|
||||
public sunExpression Argument { get { return this[0] as sunExpression; } }
|
||||
|
||||
public sunFloatCast(sunSourceLocation location)
|
||||
: base(location)
|
||||
{
|
||||
: base(location) { }
|
||||
|
||||
}
|
||||
|
||||
public override void Compile(sunContext context)
|
||||
{
|
||||
public override void Compile(sunContext context) {
|
||||
var builtinInfo = context.ResolveSystemBuiltin("float");
|
||||
Argument.Compile(context);
|
||||
context.Text.CallBuiltin(builtinInfo.Index, 1);
|
||||
}
|
||||
}
|
||||
|
||||
class sunTypeofCast : sunNode
|
||||
{
|
||||
class sunTypeofCast : sunNode {
|
||||
public sunExpression Argument { get { return this[0] as sunExpression; } }
|
||||
|
||||
public sunTypeofCast(sunSourceLocation location)
|
||||
: base(location)
|
||||
{
|
||||
: base(location) { }
|
||||
|
||||
}
|
||||
|
||||
public override void Compile(sunContext context)
|
||||
{
|
||||
public override void Compile(sunContext context) {
|
||||
var builtinInfo = context.ResolveSystemBuiltin("typeof");
|
||||
Argument.Compile(context);
|
||||
context.Text.CallBuiltin(builtinInfo.Index, 1);
|
||||
}
|
||||
}
|
||||
|
||||
class sunPrint : sunNode
|
||||
{
|
||||
class sunPrint : sunNode {
|
||||
public sunNode ArgumentList { get { return this[0]; } }
|
||||
|
||||
public sunPrint(sunSourceLocation location)
|
||||
: base(location)
|
||||
{
|
||||
: base(location) { }
|
||||
|
||||
}
|
||||
|
||||
public override void Compile(sunContext context)
|
||||
{
|
||||
public override void Compile(sunContext context) {
|
||||
var builtinInfo = context.ResolveSystemBuiltin("print");
|
||||
ArgumentList.Compile(context);
|
||||
context.Text.CallBuiltin(builtinInfo.Index, ArgumentList.Count);
|
||||
|
|
|
@ -1,33 +1,22 @@
|
|||
namespace arookas
|
||||
{
|
||||
class sunStorableReference : sunNode
|
||||
{
|
||||
namespace arookas {
|
||||
class sunStorableReference : sunNode {
|
||||
public sunIdentifier Storable { get { return this[0] as sunIdentifier; } }
|
||||
|
||||
public sunStorableReference(sunSourceLocation location)
|
||||
: base(location)
|
||||
{
|
||||
: base(location) { }
|
||||
|
||||
}
|
||||
|
||||
public override void Compile(sunContext context)
|
||||
{
|
||||
public override void Compile(sunContext context) {
|
||||
context.MustResolveStorable(Storable).Compile(context);
|
||||
}
|
||||
}
|
||||
|
||||
class sunVariableDeclaration : sunNode
|
||||
{
|
||||
class sunVariableDeclaration : sunNode {
|
||||
public sunIdentifier Variable { get { return this[0] as sunIdentifier; } }
|
||||
|
||||
public sunVariableDeclaration(sunSourceLocation location)
|
||||
: base(location)
|
||||
{
|
||||
: base(location) { }
|
||||
|
||||
}
|
||||
|
||||
public override void Compile(sunContext context)
|
||||
{
|
||||
public override void Compile(sunContext context) {
|
||||
context.DeclareVariable(Variable);
|
||||
}
|
||||
}
|
||||
|
@ -39,13 +28,9 @@
|
|||
public sunExpression Expression { get { return this[2] as sunExpression; } }
|
||||
|
||||
public sunVariableDefinition(sunSourceLocation location)
|
||||
: base(location)
|
||||
{
|
||||
: base(location) { }
|
||||
|
||||
}
|
||||
|
||||
public override void Compile(sunContext context)
|
||||
{
|
||||
public override void Compile(sunContext context) {
|
||||
var symbol = context.DeclareVariable(Variable);
|
||||
Operator.Compile(context, symbol, Expression);
|
||||
}
|
||||
|
@ -58,16 +43,11 @@
|
|||
public sunExpression Expression { get { return this[2] as sunExpression; } }
|
||||
|
||||
public sunStorableAssignment(sunSourceLocation location)
|
||||
: base(location)
|
||||
{
|
||||
: base(location) { }
|
||||
|
||||
}
|
||||
|
||||
public override void Compile(sunContext context)
|
||||
{
|
||||
public override void Compile(sunContext context) {
|
||||
var symbol = context.MustResolveStorable(Storable);
|
||||
if (symbol is sunConstantSymbol)
|
||||
{
|
||||
if (symbol is sunConstantSymbol) {
|
||||
throw new sunAssignConstantException(Storable);
|
||||
}
|
||||
Operator.Compile(context, symbol, Expression);
|
||||
|
@ -80,13 +60,9 @@
|
|||
public sunExpression Expression { get { return this[2] as sunExpression; } }
|
||||
|
||||
public sunConstantDefinition(sunSourceLocation location)
|
||||
: base(location)
|
||||
{
|
||||
: base(location) { }
|
||||
|
||||
}
|
||||
|
||||
public override void Compile(sunContext context)
|
||||
{
|
||||
public override void Compile(sunContext context) {
|
||||
context.DeclareConstant(Constant, Expression);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,46 +2,35 @@
|
|||
using System.Diagnostics;
|
||||
using System.IO;
|
||||
|
||||
namespace arookas
|
||||
{
|
||||
public class sunCompiler
|
||||
{
|
||||
public sunCompilerResults Compile(string name, Stream output)
|
||||
{
|
||||
namespace arookas {
|
||||
public class sunCompiler {
|
||||
public sunCompilerResults Compile(string name, Stream output) {
|
||||
return Compile(name, output, sunImportResolver.Default);
|
||||
}
|
||||
public sunCompilerResults Compile(string name, Stream output, sunImportResolver resolver)
|
||||
{
|
||||
if (name == null)
|
||||
{
|
||||
public sunCompilerResults Compile(string name, Stream output, sunImportResolver resolver) {
|
||||
if (name == null) {
|
||||
throw new ArgumentNullException("name");
|
||||
}
|
||||
if (output == null)
|
||||
{
|
||||
if (output == null) {
|
||||
throw new ArgumentNullException("output");
|
||||
}
|
||||
if (resolver == null)
|
||||
{
|
||||
if (resolver == null) {
|
||||
throw new ArgumentNullException("resolver");
|
||||
}
|
||||
var context = new sunContext();
|
||||
var results = new sunCompilerResults();
|
||||
var timer = Stopwatch.StartNew();
|
||||
try
|
||||
{
|
||||
try {
|
||||
context.Open(output, resolver);
|
||||
var result = context.Import(name);
|
||||
if (result != sunImportResult.Loaded)
|
||||
{
|
||||
if (result != sunImportResult.Loaded) {
|
||||
throw new sunImportException(name, result);
|
||||
}
|
||||
context.Text.Terminate(); // NOTETOSELF: don't do this via sunNode.Compile because imported files will add this as well
|
||||
foreach (var function in context.SymbolTable.Functions)
|
||||
{
|
||||
foreach (var function in context.SymbolTable.Functions) {
|
||||
function.Compile(context);
|
||||
}
|
||||
foreach (var function in context.SymbolTable.Functions)
|
||||
{
|
||||
foreach (var function in context.SymbolTable.Functions) {
|
||||
function.CloseCallSites(context);
|
||||
}
|
||||
results.DataCount = context.DataTable.Count;
|
||||
|
@ -51,8 +40,7 @@ namespace arookas
|
|||
results.VariableCount = context.SymbolTable.VariableCount;
|
||||
context.Close();
|
||||
}
|
||||
catch (sunCompilerException ex)
|
||||
{
|
||||
catch (sunCompilerException ex) {
|
||||
results.Error = ex;
|
||||
}
|
||||
timer.Stop();
|
||||
|
@ -61,8 +49,7 @@ namespace arookas
|
|||
}
|
||||
}
|
||||
|
||||
public class sunCompilerResults
|
||||
{
|
||||
public class sunCompilerResults {
|
||||
// success
|
||||
public bool Success { get { return Error == null; } }
|
||||
public sunCompilerException Error { get; internal set; }
|
||||
|
|
157
ssc/context.cs
157
ssc/context.cs
|
@ -4,10 +4,8 @@ using System.IO;
|
|||
using System.Linq;
|
||||
using System.Text;
|
||||
|
||||
namespace arookas
|
||||
{
|
||||
class sunContext
|
||||
{
|
||||
namespace arookas {
|
||||
class sunContext {
|
||||
bool mOpen;
|
||||
aBinaryWriter mWriter;
|
||||
uint mTextOffset, mDataOffset, mSymbolOffset;
|
||||
|
@ -19,8 +17,7 @@ namespace arookas
|
|||
public sunLoopStack Loops { get; private set; }
|
||||
public sunImportResolver ImportResolver { get; private set; }
|
||||
|
||||
public sunContext()
|
||||
{
|
||||
public sunContext() {
|
||||
DataTable = new sunDataTable();
|
||||
SymbolTable = new sunSymbolTable();
|
||||
Scopes = new sunScopeStack();
|
||||
|
@ -28,22 +25,15 @@ namespace arookas
|
|||
}
|
||||
|
||||
// open/close
|
||||
public void Open(Stream output)
|
||||
{
|
||||
Open(output, sunImportResolver.Default);
|
||||
}
|
||||
public void Open(Stream output, sunImportResolver importResolver)
|
||||
{
|
||||
if (mOpen)
|
||||
{
|
||||
public void Open(Stream output) { Open(output, sunImportResolver.Default); }
|
||||
public void Open(Stream output, sunImportResolver importResolver) {
|
||||
if (mOpen) {
|
||||
throw new InvalidOperationException();
|
||||
}
|
||||
if (output == null)
|
||||
{
|
||||
if (output == null) {
|
||||
throw new ArgumentNullException("output");
|
||||
}
|
||||
if (importResolver == null)
|
||||
{
|
||||
if (importResolver == null) {
|
||||
throw new ArgumentNullException("importResolver");
|
||||
}
|
||||
mOpen = true;
|
||||
|
@ -73,10 +63,8 @@ namespace arookas
|
|||
DeclareSystemBuiltin("typeof", false, "x");
|
||||
DeclareSystemBuiltin("print", true);
|
||||
}
|
||||
public void Close()
|
||||
{
|
||||
if (!mOpen)
|
||||
{
|
||||
public void Close() {
|
||||
if (!mOpen) {
|
||||
throw new InvalidOperationException();
|
||||
}
|
||||
mWriter.PopAnchor();
|
||||
|
@ -90,26 +78,21 @@ namespace arookas
|
|||
}
|
||||
|
||||
// imports/compilation
|
||||
public sunImportResult Import(string name)
|
||||
{
|
||||
if (name == null)
|
||||
{
|
||||
public sunImportResult Import(string name) {
|
||||
if (name == null) {
|
||||
throw new ArgumentNullException("name");
|
||||
}
|
||||
sunScriptFile file;
|
||||
var result = ImportResolver.ResolveImport(name, out file);
|
||||
if (result == sunImportResult.Loaded)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (result == sunImportResult.Loaded) {
|
||||
try {
|
||||
ImportResolver.EnterFile(file);
|
||||
var parser = new sunParser();
|
||||
var tree = parser.Parse(file);
|
||||
tree.Compile(this);
|
||||
ImportResolver.ExitFile(file);
|
||||
}
|
||||
finally
|
||||
{
|
||||
finally {
|
||||
file.Dispose();
|
||||
}
|
||||
}
|
||||
|
@ -117,82 +100,68 @@ namespace arookas
|
|||
}
|
||||
|
||||
// callables
|
||||
public sunBuiltinSymbol DeclareBuiltin(sunBuiltinDeclaration node)
|
||||
{
|
||||
if (SymbolTable.Callables.Any(i => i.Name == node.Builtin.Value))
|
||||
{
|
||||
public sunBuiltinSymbol DeclareBuiltin(sunBuiltinDeclaration node) {
|
||||
if (SymbolTable.Callables.Any(i => i.Name == node.Builtin.Value)) {
|
||||
throw new sunRedeclaredBuiltinException(node);
|
||||
}
|
||||
var symbol = new sunBuiltinSymbol(node.Builtin.Value, node.Parameters.ParameterInfo, SymbolTable.Count);
|
||||
SymbolTable.Add(symbol);
|
||||
return symbol;
|
||||
}
|
||||
public sunFunctionSymbol DefineFunction(sunFunctionDefinition node)
|
||||
{
|
||||
if (node.Parameters.IsVariadic)
|
||||
{
|
||||
public sunFunctionSymbol DefineFunction(sunFunctionDefinition node) {
|
||||
if (node.Parameters.IsVariadic) {
|
||||
throw new sunVariadicFunctionException(node);
|
||||
}
|
||||
if (SymbolTable.Callables.Any(i => i.Name == node.Function.Value))
|
||||
{
|
||||
if (SymbolTable.Callables.Any(i => i.Name == node.Function.Value)) {
|
||||
throw new sunRedefinedFunctionException(node);
|
||||
}
|
||||
var symbol = new sunFunctionSymbol(node.Function.Value, node.Parameters.ParameterInfo, node.Body);
|
||||
SymbolTable.Add(symbol);
|
||||
return symbol;
|
||||
}
|
||||
public sunCallableSymbol ResolveCallable(sunFunctionCall node)
|
||||
{
|
||||
public sunCallableSymbol ResolveCallable(sunFunctionCall node) {
|
||||
var symbol = SymbolTable.Callables.FirstOrDefault(i => i.Name == node.Function.Value);
|
||||
if (symbol == null)
|
||||
{
|
||||
if (symbol == null) {
|
||||
throw new sunUndefinedFunctionException(node);
|
||||
}
|
||||
return symbol;
|
||||
}
|
||||
public sunCallableSymbol MustResolveCallable(sunFunctionCall node)
|
||||
{
|
||||
public sunCallableSymbol MustResolveCallable(sunFunctionCall node) {
|
||||
var symbol = ResolveCallable(node);
|
||||
if (symbol == null)
|
||||
{
|
||||
if (symbol == null) {
|
||||
throw new sunUndefinedFunctionException(node);
|
||||
}
|
||||
return symbol;
|
||||
}
|
||||
|
||||
public sunBuiltinSymbol DeclareSystemBuiltin(string name, bool variadic, params string[] parameters)
|
||||
{
|
||||
public sunBuiltinSymbol DeclareSystemBuiltin(string name, bool variadic, params string[] parameters) {
|
||||
var symbol = SymbolTable.Builtins.FirstOrDefault(i => i.Name == name);
|
||||
if (symbol == null)
|
||||
{
|
||||
if (symbol == null) {
|
||||
symbol = new sunBuiltinSymbol(name, new sunParameterInfo(parameters, variadic), SymbolTable.Count);
|
||||
SymbolTable.Add(symbol);
|
||||
}
|
||||
return symbol;
|
||||
}
|
||||
public sunBuiltinSymbol ResolveSystemBuiltin(string name)
|
||||
{
|
||||
public sunBuiltinSymbol ResolveSystemBuiltin(string name) {
|
||||
return SymbolTable.Builtins.FirstOrDefault(i => i.Name == name);
|
||||
}
|
||||
|
||||
// storables
|
||||
public sunVariableSymbol DeclareVariable(sunIdentifier node)
|
||||
{
|
||||
public sunVariableSymbol DeclareVariable(sunIdentifier node) {
|
||||
#if SSC_RESOLVEVAR_NEST
|
||||
if (Scopes.Top.GetIsDeclared(node.Value))
|
||||
#else
|
||||
if (Scopes.Any(i => i.GetIsDeclared(node.Value)))
|
||||
#endif
|
||||
{
|
||||
if (Scopes.Top.GetIsDeclared(node.Value)) {
|
||||
throw new sunRedeclaredVariableException(node);
|
||||
}
|
||||
#else
|
||||
if (Scopes.Any(i => i.GetIsDeclared(node.Value))) {
|
||||
throw new sunRedeclaredVariableException(node);
|
||||
}
|
||||
#endif
|
||||
var symbol = Scopes.DeclareVariable(node.Value);
|
||||
if (Scopes.Top.Type == sunScopeType.Script) // global-scope variables are added to the symbol table
|
||||
{
|
||||
if (Scopes.Top.Type == sunScopeType.Script) { // global-scope variables are added to the symbol table
|
||||
#if SSC_RESOLVEVAR_NEST
|
||||
// only add the variable symbol if there isn't one with this index already
|
||||
if (!SymbolTable.Variables.Any(i => i.Index == symbol.Index))
|
||||
{
|
||||
if (!SymbolTable.Variables.Any(i => i.Index == symbol.Index)) {
|
||||
SymbolTable.Add(new sunVariableSymbol(String.Format("global{0}", symbol.Index), symbol.Display, symbol.Index));
|
||||
}
|
||||
#else
|
||||
|
@ -201,68 +170,52 @@ namespace arookas
|
|||
}
|
||||
return symbol;
|
||||
}
|
||||
public sunConstantSymbol DeclareConstant(sunIdentifier node, sunExpression expression)
|
||||
{
|
||||
public sunConstantSymbol DeclareConstant(sunIdentifier node, sunExpression expression) {
|
||||
#if SSC_RESOLVEVAR_NEST
|
||||
if (Scopes.Top.GetIsDeclared(node.Value))
|
||||
#else
|
||||
if (Scopes.Any(i => i.GetIsDeclared(node.Value)))
|
||||
#endif
|
||||
{
|
||||
if (Scopes.Top.GetIsDeclared(node.Value)) {
|
||||
throw new sunRedeclaredVariableException(node);
|
||||
}
|
||||
#else
|
||||
if (Scopes.Any(i => i.GetIsDeclared(node.Value))) {
|
||||
throw new sunRedeclaredVariableException(node);
|
||||
}
|
||||
#endif
|
||||
return Scopes.DeclareConstant(node.Value, expression);
|
||||
}
|
||||
public sunStorableSymbol ResolveStorable(sunIdentifier node)
|
||||
{
|
||||
for (int i = Scopes.Count - 1; i >= 0; --i)
|
||||
{
|
||||
public sunStorableSymbol ResolveStorable(sunIdentifier node) {
|
||||
for (int i = Scopes.Count - 1; i >= 0; --i) {
|
||||
var symbol = Scopes[i].ResolveStorable(node.Value);
|
||||
if (symbol != null)
|
||||
{
|
||||
if (symbol != null) {
|
||||
return symbol;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
public sunVariableSymbol ResolveVariable(sunIdentifier node)
|
||||
{
|
||||
return ResolveStorable(node) as sunVariableSymbol;
|
||||
}
|
||||
public sunConstantSymbol ResolveConstant(sunIdentifier node)
|
||||
{
|
||||
return ResolveStorable(node) as sunConstantSymbol;
|
||||
}
|
||||
public sunStorableSymbol MustResolveStorable(sunIdentifier node)
|
||||
{
|
||||
public sunVariableSymbol ResolveVariable(sunIdentifier node) { return ResolveStorable(node) as sunVariableSymbol; }
|
||||
public sunConstantSymbol ResolveConstant(sunIdentifier node) { return ResolveStorable(node) as sunConstantSymbol; }
|
||||
public sunStorableSymbol MustResolveStorable(sunIdentifier node) {
|
||||
var symbol = ResolveStorable(node);
|
||||
if (symbol == null)
|
||||
{
|
||||
if (symbol == null) {
|
||||
throw new sunUndeclaredVariableException(node);
|
||||
}
|
||||
return symbol;
|
||||
}
|
||||
public sunVariableSymbol MustResolveVariable(sunIdentifier node)
|
||||
{
|
||||
public sunVariableSymbol MustResolveVariable(sunIdentifier node) {
|
||||
var symbol = ResolveVariable(node);
|
||||
if (symbol == null)
|
||||
{
|
||||
if (symbol == null) {
|
||||
throw new sunUndeclaredVariableException(node);
|
||||
}
|
||||
return symbol;
|
||||
}
|
||||
public sunConstantSymbol MustResolveConstant(sunIdentifier node)
|
||||
{
|
||||
public sunConstantSymbol MustResolveConstant(sunIdentifier node) {
|
||||
var symbol = ResolveConstant(node);
|
||||
if (symbol == null)
|
||||
{
|
||||
if (symbol == null) {
|
||||
throw new sunUndeclaredVariableException(node);
|
||||
}
|
||||
return symbol;
|
||||
}
|
||||
|
||||
void WriteHeader()
|
||||
{
|
||||
void WriteHeader() {
|
||||
mWriter.WriteString("SPCB");
|
||||
mWriter.Write32(mTextOffset);
|
||||
mWriter.Write32(mDataOffset);
|
||||
|
|
|
@ -2,19 +2,15 @@
|
|||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace arookas
|
||||
{
|
||||
class sunDataTable : IEnumerable<string>
|
||||
{
|
||||
namespace arookas {
|
||||
class sunDataTable : IEnumerable<string> {
|
||||
List<string> data = new List<string>(10);
|
||||
|
||||
public int Count { get { return data.Count; } }
|
||||
|
||||
public int Add(string value)
|
||||
{
|
||||
public int Add(string value) {
|
||||
int index = data.IndexOf(value);
|
||||
if (index < 0)
|
||||
{
|
||||
if (index < 0) {
|
||||
index = data.Count;
|
||||
data.Add(value);
|
||||
}
|
||||
|
@ -22,17 +18,14 @@ namespace arookas
|
|||
}
|
||||
public void Clear() { data.Clear(); }
|
||||
|
||||
public void Write(aBinaryWriter writer)
|
||||
{
|
||||
public void Write(aBinaryWriter writer) {
|
||||
int ofs = 0;
|
||||
foreach (var value in this)
|
||||
{
|
||||
foreach (var value in this) {
|
||||
writer.WriteS32(ofs);
|
||||
var length = writer.Encoding.GetByteCount(value);
|
||||
ofs += length + 1; // include terminator
|
||||
}
|
||||
foreach (var value in this)
|
||||
{
|
||||
foreach (var value in this) {
|
||||
writer.WriteString(value, aBinaryStringFormat.NullTerminated);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,67 +1,53 @@
|
|||
using PerCederberg.Grammatica.Runtime;
|
||||
using System;
|
||||
|
||||
namespace arookas
|
||||
{
|
||||
namespace arookas {
|
||||
// base exception type
|
||||
public class sunCompilerException : Exception
|
||||
{
|
||||
public sunCompilerException()
|
||||
{
|
||||
public class sunCompilerException : Exception {
|
||||
public sunCompilerException() {
|
||||
|
||||
}
|
||||
public sunCompilerException(string format, params object[] args)
|
||||
: base(String.Format(format, args))
|
||||
{
|
||||
: base(String.Format(format, args)) {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
// exceptions that have a location in the source
|
||||
public abstract class sunSourceException : sunCompilerException
|
||||
{
|
||||
public abstract class sunSourceException : sunCompilerException {
|
||||
public abstract sunSourceLocation Location { get; }
|
||||
|
||||
public sunSourceException()
|
||||
{
|
||||
public sunSourceException() {
|
||||
|
||||
}
|
||||
public sunSourceException(string format, params object[] args)
|
||||
: base(format, args)
|
||||
{
|
||||
: base(format, args) {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
public class sunImportException : sunCompilerException
|
||||
{
|
||||
public class sunImportException : sunCompilerException {
|
||||
public string Name { get; private set; }
|
||||
public sunImportResult Result { get; private set; }
|
||||
public override string Message
|
||||
{
|
||||
get
|
||||
{
|
||||
public override string Message {
|
||||
get {
|
||||
string format;
|
||||
switch (Result)
|
||||
{
|
||||
case sunImportResult.Loaded: format = "Script '{0}' loaded successfully."; break; // Error: Success!
|
||||
case sunImportResult.Skipped: format = "Script '{0}' was skipped."; break;
|
||||
case sunImportResult.Missing: format = "Script '{0}' could not be found."; break;
|
||||
case sunImportResult.FailedToLoad: format = "Script '{0}' failed to load."; break;
|
||||
default: format = "Name: {0}, Result: {1}"; break;
|
||||
switch (Result) {
|
||||
case sunImportResult.Loaded: format = "Script '{0}' loaded successfully."; break; // Error: Success!
|
||||
case sunImportResult.Skipped: format = "Script '{0}' was skipped."; break;
|
||||
case sunImportResult.Missing: format = "Script '{0}' could not be found."; break;
|
||||
case sunImportResult.FailedToLoad: format = "Script '{0}' failed to load."; break;
|
||||
default: format = "Name: {0}, Result: {1}"; break;
|
||||
}
|
||||
return String.Format(format, Name, Result);
|
||||
}
|
||||
}
|
||||
|
||||
public sunImportException(string name, sunImportResult result)
|
||||
{
|
||||
if (name == null)
|
||||
{
|
||||
public sunImportException(string name, sunImportResult result) {
|
||||
if (name == null) {
|
||||
throw new ArgumentNullException("name");
|
||||
}
|
||||
if (!result.IsDefined())
|
||||
{
|
||||
if (!result.IsDefined()) {
|
||||
throw new ArgumentOutOfRangeException("name");
|
||||
}
|
||||
Name = name;
|
||||
|
@ -70,22 +56,18 @@ namespace arookas
|
|||
}
|
||||
|
||||
// wrapper around Grammatica exceptions
|
||||
class sunParserException : sunSourceException
|
||||
{
|
||||
class sunParserException : sunSourceException {
|
||||
string file;
|
||||
|
||||
public ParseException Info { get; private set; }
|
||||
public override string Message { get { return Info.ErrorMessage; } }
|
||||
public override sunSourceLocation Location { get { return new sunSourceLocation(file, Info.Line, Info.Column); } }
|
||||
|
||||
public sunParserException(string file, ParseException info)
|
||||
{
|
||||
if (file == null)
|
||||
{
|
||||
public sunParserException(string file, ParseException info) {
|
||||
if (file == null) {
|
||||
throw new ArgumentNullException("file");
|
||||
}
|
||||
if (info == null)
|
||||
{
|
||||
if (info == null) {
|
||||
throw new ArgumentNullException("info");
|
||||
}
|
||||
this.file = file;
|
||||
|
@ -94,143 +76,114 @@ namespace arookas
|
|||
}
|
||||
|
||||
// node exceptions
|
||||
abstract class sunNodeException<TNode> : sunSourceException where TNode : sunNode
|
||||
{
|
||||
abstract class sunNodeException<TNode> : sunSourceException where TNode : sunNode {
|
||||
public TNode Node { get; private set; }
|
||||
public override sunSourceLocation Location { get { return Node.Location; } }
|
||||
|
||||
protected sunNodeException(TNode node)
|
||||
{
|
||||
if (node == null)
|
||||
{
|
||||
protected sunNodeException(TNode node) {
|
||||
if (node == null) {
|
||||
throw new ArgumentNullException("node");
|
||||
}
|
||||
Node = node;
|
||||
}
|
||||
}
|
||||
|
||||
class sunRedeclaredBuiltinException : sunNodeException<sunBuiltinDeclaration>
|
||||
{
|
||||
class sunRedeclaredBuiltinException : sunNodeException<sunBuiltinDeclaration> {
|
||||
public override string Message { get { return String.Format("Redeclared builtin '{0}'.", Node.Builtin.Value); } }
|
||||
|
||||
public sunRedeclaredBuiltinException(sunBuiltinDeclaration node)
|
||||
: base(node)
|
||||
{
|
||||
: base(node) {
|
||||
|
||||
}
|
||||
}
|
||||
class sunUndefinedFunctionException : sunNodeException<sunFunctionCall>
|
||||
{
|
||||
class sunUndefinedFunctionException : sunNodeException<sunFunctionCall> {
|
||||
public override string Message { get { return String.Format("Undefined function or builtin '{0}'.", Node.Function.Value); } }
|
||||
|
||||
public sunUndefinedFunctionException(sunFunctionCall node)
|
||||
: base(node)
|
||||
{
|
||||
: base(node) {
|
||||
|
||||
}
|
||||
}
|
||||
class sunRedefinedFunctionException : sunNodeException<sunFunctionDefinition>
|
||||
{
|
||||
class sunRedefinedFunctionException : sunNodeException<sunFunctionDefinition> {
|
||||
public override string Message { get { return String.Format("Redefined function '{0}'.", Node.Function.Value); } }
|
||||
|
||||
public sunRedefinedFunctionException(sunFunctionDefinition node)
|
||||
: base(node)
|
||||
{
|
||||
: base(node) {
|
||||
|
||||
}
|
||||
}
|
||||
class sunUndeclaredVariableException : sunNodeException<sunIdentifier>
|
||||
{
|
||||
class sunUndeclaredVariableException : sunNodeException<sunIdentifier> {
|
||||
public override string Message { get { return String.Format("Undeclared variable '{0}'.", Node.Value); } }
|
||||
|
||||
public sunUndeclaredVariableException(sunIdentifier node)
|
||||
: base(node)
|
||||
{
|
||||
: base(node) {
|
||||
|
||||
}
|
||||
}
|
||||
class sunRedeclaredVariableException : sunNodeException<sunIdentifier>
|
||||
{
|
||||
class sunRedeclaredVariableException : sunNodeException<sunIdentifier> {
|
||||
public override string Message { get { return String.Format("Redeclared variable '{0}'.", Node.Value); } }
|
||||
|
||||
public sunRedeclaredVariableException(sunIdentifier node)
|
||||
: base(node)
|
||||
{
|
||||
: base(node) {
|
||||
|
||||
}
|
||||
}
|
||||
class sunAssignConstantException : sunNodeException<sunIdentifier>
|
||||
{
|
||||
class sunAssignConstantException : sunNodeException<sunIdentifier> {
|
||||
public override string Message { get { return String.Format("Constant '{0}' is read-only.", Node.Value); } }
|
||||
|
||||
public sunAssignConstantException(sunIdentifier node)
|
||||
: base(node)
|
||||
{
|
||||
: base(node) {
|
||||
|
||||
}
|
||||
}
|
||||
class sunRedeclaredParameterException : sunNodeException<sunIdentifier>
|
||||
{
|
||||
class sunRedeclaredParameterException : sunNodeException<sunIdentifier> {
|
||||
public override string Message { get { return String.Format("Redeclared parameter '{0}'.", Node.Value); } }
|
||||
|
||||
public sunRedeclaredParameterException(sunIdentifier node)
|
||||
: base(node)
|
||||
{
|
||||
: base(node) {
|
||||
|
||||
}
|
||||
}
|
||||
class sunVariadicFunctionException : sunNodeException<sunFunctionDefinition>
|
||||
{
|
||||
class sunVariadicFunctionException : sunNodeException<sunFunctionDefinition> {
|
||||
public override string Message { get { return String.Format("Function '{0}' is defined as a variadic function (only builtins may be variadic).", Node.Function.Value); } }
|
||||
|
||||
public sunVariadicFunctionException(sunFunctionDefinition node)
|
||||
: base(node)
|
||||
{
|
||||
: base(node) {
|
||||
|
||||
}
|
||||
}
|
||||
class sunEscapeSequenceException : sunNodeException<sunStringLiteral>
|
||||
{
|
||||
class sunEscapeSequenceException : sunNodeException<sunStringLiteral> {
|
||||
public override string Message { get { return String.Format("Bad escape sequence in string."); } }
|
||||
|
||||
public sunEscapeSequenceException(sunStringLiteral node)
|
||||
: base(node)
|
||||
{
|
||||
: base(node) {
|
||||
|
||||
}
|
||||
}
|
||||
class sunVariadicParameterListException : sunNodeException<sunParameterList>
|
||||
{
|
||||
class sunVariadicParameterListException : sunNodeException<sunParameterList> {
|
||||
public override string Message { get { return String.Format("Bad variadic parameter list."); } }
|
||||
|
||||
public sunVariadicParameterListException(sunParameterList node)
|
||||
: base(node)
|
||||
{
|
||||
: base(node) {
|
||||
|
||||
}
|
||||
}
|
||||
class sunArgumentCountException : sunNodeException<sunFunctionCall>
|
||||
{
|
||||
class sunArgumentCountException : sunNodeException<sunFunctionCall> {
|
||||
public sunCallableSymbol CalledSymbol { get; private set; }
|
||||
public int ArgumentMinimum { get { return CalledSymbol.Parameters.Minimum; } }
|
||||
public int ArgumentCount { get { return Node.Arguments.Count; } }
|
||||
|
||||
public override string Message
|
||||
{
|
||||
get
|
||||
{
|
||||
public override string Message {
|
||||
get {
|
||||
string format;
|
||||
if (CalledSymbol.Parameters.IsVariadic)
|
||||
{
|
||||
if (CalledSymbol.Parameters.IsVariadic) {
|
||||
// assuming to be missing because there's only a minimum
|
||||
format = "Missing {0} argument(s) (expected at least {1}; got {2}).";
|
||||
}
|
||||
else if (Node.Arguments.Count < CalledSymbol.Parameters.Minimum)
|
||||
{
|
||||
else if (Node.Arguments.Count < CalledSymbol.Parameters.Minimum) {
|
||||
format = "Missing {0} argument(s) (expected {1}; got {2})."; // missing arguments
|
||||
}
|
||||
else
|
||||
{
|
||||
else {
|
||||
format = "Too many arguments (expected {1}; got {2})."; // extra arguments
|
||||
}
|
||||
return String.Format(format, ArgumentMinimum - ArgumentCount, ArgumentMinimum, ArgumentCount);
|
||||
|
@ -238,52 +191,42 @@ namespace arookas
|
|||
}
|
||||
|
||||
public sunArgumentCountException(sunFunctionCall node, sunCallableSymbol calledSymbol)
|
||||
: base(node)
|
||||
{
|
||||
if (calledSymbol == null)
|
||||
{
|
||||
: base(node) {
|
||||
if (calledSymbol == null) {
|
||||
throw new ArgumentNullException("calledSymbol");
|
||||
}
|
||||
CalledSymbol = calledSymbol;
|
||||
}
|
||||
}
|
||||
class sunIdentifierException : sunNodeException<sunIdentifier>
|
||||
{
|
||||
class sunIdentifierException : sunNodeException<sunIdentifier> {
|
||||
public override string Message { get { return String.Format("Invalid identifier '{0}'.", Node.Value); } }
|
||||
|
||||
public sunIdentifierException(sunIdentifier node)
|
||||
: base(node)
|
||||
{
|
||||
: base(node) {
|
||||
|
||||
}
|
||||
}
|
||||
class sunMissingImportException : sunNodeException<sunImport>
|
||||
{
|
||||
class sunMissingImportException : sunNodeException<sunImport> {
|
||||
public override string Message { get { return String.Format("Could not find import file '{0}'.", Node.ImportFile.Value); } }
|
||||
|
||||
public sunMissingImportException(sunImport node)
|
||||
: base(node)
|
||||
{
|
||||
: base(node) {
|
||||
|
||||
}
|
||||
}
|
||||
class sunBreakException : sunNodeException<sunBreak>
|
||||
{
|
||||
class sunBreakException : sunNodeException<sunBreak> {
|
||||
public override string Message { get { return "Break statements must be placed within a loop statement."; } }
|
||||
|
||||
public sunBreakException(sunBreak node)
|
||||
: base(node)
|
||||
{
|
||||
: base(node) {
|
||||
|
||||
}
|
||||
}
|
||||
class sunContinueException : sunNodeException<sunContinue>
|
||||
{
|
||||
class sunContinueException : sunNodeException<sunContinue> {
|
||||
public override string Message { get { return "Continue statements must be placed within a loop statement."; } }
|
||||
|
||||
public sunContinueException(sunContinue node)
|
||||
: base(node)
|
||||
{
|
||||
: base(node) {
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,10 +3,8 @@ using System.Collections.Generic;
|
|||
using System.IO;
|
||||
using System.Linq;
|
||||
|
||||
namespace arookas
|
||||
{
|
||||
public abstract class sunImportResolver
|
||||
{
|
||||
namespace arookas {
|
||||
public abstract class sunImportResolver {
|
||||
static sunImportResolver defaultResolver = new sunDefaultImportResolver();
|
||||
public static sunImportResolver Default { get { return defaultResolver; } }
|
||||
|
||||
|
@ -15,60 +13,49 @@ namespace arookas
|
|||
public abstract sunImportResult ResolveImport(string name, out sunScriptFile file);
|
||||
|
||||
// default implementation
|
||||
sealed class sunDefaultImportResolver : sunImportResolver
|
||||
{
|
||||
sealed class sunDefaultImportResolver : sunImportResolver {
|
||||
List<sunScriptFile> imports = new List<sunScriptFile>(10);
|
||||
Stack<sunScriptFile> current = new Stack<sunScriptFile>(5);
|
||||
string rootDirectory, currentDirectory;
|
||||
string CurrentDirectory { get { return current.Count > 0 ? Path.GetDirectoryName(current.Peek().Name) : currentDirectory; } }
|
||||
|
||||
public sunDefaultImportResolver()
|
||||
{
|
||||
public sunDefaultImportResolver() {
|
||||
rootDirectory = AppDomain.CurrentDomain.BaseDirectory;
|
||||
currentDirectory = Directory.GetCurrentDirectory();
|
||||
}
|
||||
|
||||
public override void EnterFile(sunScriptFile file) { current.Push(file); }
|
||||
public override void ExitFile(sunScriptFile file) { current.Pop(); }
|
||||
public override sunImportResult ResolveImport(string name, out sunScriptFile file)
|
||||
{
|
||||
public override sunImportResult ResolveImport(string name, out sunScriptFile file) {
|
||||
file = null;
|
||||
string fullPath;
|
||||
if (Path.IsPathRooted(name))
|
||||
{
|
||||
if (Path.IsPathRooted(name)) {
|
||||
// if the path is absolute, just use it directly
|
||||
fullPath = name;
|
||||
if (!File.Exists(fullPath))
|
||||
{
|
||||
if (!File.Exists(fullPath)) {
|
||||
return sunImportResult.Missing;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
else {
|
||||
// check if the file exists relative to the current one;
|
||||
// if it's not there, check the root directory
|
||||
fullPath = Path.Combine(CurrentDirectory, name);
|
||||
if (!File.Exists(fullPath))
|
||||
{
|
||||
if (!File.Exists(fullPath)) {
|
||||
fullPath = Path.Combine(rootDirectory, name);
|
||||
if (!File.Exists(fullPath))
|
||||
{
|
||||
if (!File.Exists(fullPath)) {
|
||||
return sunImportResult.Missing;
|
||||
}
|
||||
}
|
||||
}
|
||||
// make sure the file has not been imported yet
|
||||
if (imports.Any(i => i.Name == fullPath))
|
||||
{
|
||||
if (imports.Any(i => i.Name == fullPath)) {
|
||||
return sunImportResult.Skipped;
|
||||
}
|
||||
// open the file
|
||||
try
|
||||
{
|
||||
try {
|
||||
file = new sunScriptFile(name, File.OpenRead(fullPath));
|
||||
}
|
||||
catch
|
||||
{
|
||||
catch {
|
||||
return sunImportResult.FailedToLoad;
|
||||
}
|
||||
imports.Add(file);
|
||||
|
@ -77,44 +64,36 @@ namespace arookas
|
|||
}
|
||||
}
|
||||
|
||||
public enum sunImportResult
|
||||
{
|
||||
public enum sunImportResult {
|
||||
Loaded,
|
||||
Skipped,
|
||||
Missing,
|
||||
FailedToLoad,
|
||||
}
|
||||
|
||||
public class sunScriptFile : IDisposable
|
||||
{
|
||||
public class sunScriptFile : IDisposable {
|
||||
public string Name { get; private set; }
|
||||
public Stream Stream { get; private set; }
|
||||
|
||||
public sunScriptFile(string name, Stream stream)
|
||||
{
|
||||
if (name == null)
|
||||
{
|
||||
public sunScriptFile(string name, Stream stream) {
|
||||
if (name == null) {
|
||||
throw new ArgumentNullException("name");
|
||||
}
|
||||
if (stream == null)
|
||||
{
|
||||
if (stream == null) {
|
||||
throw new ArgumentNullException("stream");
|
||||
}
|
||||
if (!stream.CanRead)
|
||||
{
|
||||
if (!stream.CanRead) {
|
||||
throw new ArgumentException("Stream does not support reading.", "stream");
|
||||
}
|
||||
Name = name;
|
||||
Stream = stream;
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
public void Dispose() {
|
||||
Stream.Dispose();
|
||||
}
|
||||
|
||||
public TextReader GetReader()
|
||||
{
|
||||
public TextReader GetReader() {
|
||||
return new StreamReader(Stream);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,10 +1,8 @@
|
|||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
||||
namespace arookas
|
||||
{
|
||||
class sunLoopStack
|
||||
{
|
||||
namespace arookas {
|
||||
class sunLoopStack {
|
||||
Stack<sunLoop> loops = new Stack<sunLoop>(5);
|
||||
sunLoop Top { get { return loops.Peek(); } }
|
||||
|
||||
|
@ -13,14 +11,11 @@ namespace arookas
|
|||
|
||||
public void Push() { Push(null); }
|
||||
public void Push(string name) { loops.Push(new sunLoop(name)); }
|
||||
public void Pop(sunContext context, sunPoint breakPoint, sunPoint continuePoint)
|
||||
{
|
||||
foreach (var _break in Top.Breaks)
|
||||
{
|
||||
public void Pop(sunContext context, sunPoint breakPoint, sunPoint continuePoint) {
|
||||
foreach (var _break in Top.Breaks) {
|
||||
context.Text.ClosePoint(_break, breakPoint.Offset);
|
||||
}
|
||||
foreach (var _continue in Top.Continues)
|
||||
{
|
||||
foreach (var _continue in Top.Continues) {
|
||||
context.Text.ClosePoint(_continue, continuePoint.Offset);
|
||||
}
|
||||
loops.Pop();
|
||||
|
@ -30,48 +25,39 @@ namespace arookas
|
|||
|
||||
public bool AddBreak(sunPoint point) { return AddBreak(point, null); }
|
||||
public bool AddContinue(sunPoint point) { return AddContinue(point, null); }
|
||||
public bool AddBreak(sunPoint point, string name)
|
||||
{
|
||||
if (Count < 1)
|
||||
{
|
||||
public bool AddBreak(sunPoint point, string name) {
|
||||
if (Count < 1) {
|
||||
return false;
|
||||
}
|
||||
var loop = name == null ? Top : this[name];
|
||||
if (loop == null)
|
||||
{
|
||||
if (loop == null) {
|
||||
return false;
|
||||
}
|
||||
loop.Breaks.Add(point);
|
||||
return true;
|
||||
}
|
||||
public bool AddContinue(sunPoint point, string name)
|
||||
{
|
||||
if (Count < 1)
|
||||
{
|
||||
public bool AddContinue(sunPoint point, string name) {
|
||||
if (Count < 1) {
|
||||
return false;
|
||||
}
|
||||
var loop = name == null ? Top : this[name];
|
||||
if (loop == null)
|
||||
{
|
||||
if (loop == null) {
|
||||
return false;
|
||||
}
|
||||
loop.Continues.Add(point);
|
||||
return true;
|
||||
}
|
||||
|
||||
class sunLoop
|
||||
{
|
||||
class sunLoop {
|
||||
public string Name { get; private set; }
|
||||
public List<sunPoint> Breaks { get; private set; }
|
||||
public List<sunPoint> Continues { get; private set; }
|
||||
|
||||
public sunLoop()
|
||||
: this(null)
|
||||
{
|
||||
: this(null) {
|
||||
|
||||
}
|
||||
public sunLoop(string name)
|
||||
{
|
||||
public sunLoop(string name) {
|
||||
Name = name;
|
||||
Breaks = new List<sunPoint>(5);
|
||||
Continues = new List<sunPoint>(5);
|
||||
|
|
112
ssc/parser.cs
112
ssc/parser.cs
|
@ -1,12 +1,9 @@
|
|||
using PerCederberg.Grammatica.Runtime;
|
||||
using System.Linq;
|
||||
|
||||
namespace arookas
|
||||
{
|
||||
class sunParser
|
||||
{
|
||||
static string[] keywords =
|
||||
{
|
||||
namespace arookas {
|
||||
class sunParser {
|
||||
static string[] keywords = {
|
||||
"import",
|
||||
"builtin", "function", "var", "const",
|
||||
"if", "while", "do", "for",
|
||||
|
@ -15,48 +12,37 @@ namespace arookas
|
|||
"true", "false",
|
||||
};
|
||||
|
||||
public sunNode Parse(sunScriptFile file)
|
||||
{
|
||||
using (var input = file.GetReader())
|
||||
{
|
||||
try
|
||||
{
|
||||
public sunNode Parse(sunScriptFile file) {
|
||||
using (var input = file.GetReader()) {
|
||||
try {
|
||||
var parser = new __sunParser(input);
|
||||
var node = parser.Parse();
|
||||
return CreateAst(file.Name, node);
|
||||
}
|
||||
catch (ParserLogException ex)
|
||||
{
|
||||
catch (ParserLogException ex) {
|
||||
throw new sunParserException(file.Name, ex[0]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static sunNode CreateAst(string file, Node node)
|
||||
{
|
||||
static sunNode CreateAst(string file, Node node) {
|
||||
var ast = ConvertNode(file, node);
|
||||
if (ast == null)
|
||||
{
|
||||
if (ast == null) {
|
||||
return null;
|
||||
}
|
||||
// children
|
||||
if (node is Production)
|
||||
{
|
||||
if (node is Production) {
|
||||
var production = node as Production;
|
||||
for (int i = 0; i < production.Count; ++i)
|
||||
{
|
||||
for (int i = 0; i < production.Count; ++i) {
|
||||
var child = CreateAst(file, production[i]);
|
||||
if (child != null)
|
||||
{
|
||||
if (child != null) {
|
||||
ast.Add(child);
|
||||
}
|
||||
}
|
||||
}
|
||||
// transcience
|
||||
if (ast.Count == 1)
|
||||
{
|
||||
switch (GetId(node))
|
||||
{
|
||||
if (ast.Count == 1) {
|
||||
switch (GetId(node)) {
|
||||
case __sunConstants.ROOT_STATEMENT:
|
||||
case __sunConstants.STATEMENT:
|
||||
case __sunConstants.COMPOUND_STATEMENT:
|
||||
|
@ -69,26 +55,22 @@ namespace arookas
|
|||
case __sunConstants.TERM:
|
||||
case __sunConstants.PARAMETER:
|
||||
case __sunConstants.ARGUMENT_LIST:
|
||||
case __sunConstants.ARGUMENT:
|
||||
{
|
||||
return ast[0];
|
||||
}
|
||||
case __sunConstants.ARGUMENT: {
|
||||
return ast[0];
|
||||
}
|
||||
}
|
||||
}
|
||||
return ast;
|
||||
}
|
||||
static sunNode ConvertNode(string file, Node node)
|
||||
{
|
||||
static sunNode ConvertNode(string file, Node node) {
|
||||
var location = new sunSourceLocation(file, node.StartLine, node.StartColumn);
|
||||
string token = null;
|
||||
if (node is Token)
|
||||
{
|
||||
if (node is Token) {
|
||||
token = (node as Token).Image;
|
||||
}
|
||||
|
||||
// statements
|
||||
switch (GetId(node))
|
||||
{
|
||||
switch (GetId(node)) {
|
||||
case __sunConstants.SCRIPT: return new sunNode(location);
|
||||
case __sunConstants.ROOT_STATEMENT: return new sunNode(location);
|
||||
case __sunConstants.STATEMENT: return new sunNode(location);
|
||||
|
@ -108,8 +90,7 @@ namespace arookas
|
|||
}
|
||||
|
||||
// literals
|
||||
switch (GetId(node))
|
||||
{
|
||||
switch (GetId(node)) {
|
||||
case __sunConstants.INT_NUMBER: return new sunIntLiteral(location, token);
|
||||
case __sunConstants.HEX_NUMBER: return new sunHexLiteral(location, token);
|
||||
case __sunConstants.DEC_NUMBER: return new sunFloatLiteral(location, token);
|
||||
|
@ -121,17 +102,14 @@ namespace arookas
|
|||
}
|
||||
|
||||
// operators
|
||||
switch (GetId(node))
|
||||
{
|
||||
switch (GetId(node)) {
|
||||
case __sunConstants.ADD: return new sunAdd(location);
|
||||
case __sunConstants.SUB:
|
||||
{
|
||||
if (GetId(node.Parent) == __sunConstants.UNARY_OPERATOR)
|
||||
{
|
||||
return new sunNeg(location);
|
||||
case __sunConstants.SUB: {
|
||||
if (GetId(node.Parent) == __sunConstants.UNARY_OPERATOR) {
|
||||
return new sunNeg(location);
|
||||
}
|
||||
return new sunSub(location);
|
||||
}
|
||||
return new sunSub(location);
|
||||
}
|
||||
case __sunConstants.MUL: return new sunMul(location);
|
||||
case __sunConstants.DIV: return new sunDiv(location);
|
||||
case __sunConstants.MOD: return new sunMod(location);
|
||||
|
@ -175,12 +153,11 @@ namespace arookas
|
|||
}
|
||||
|
||||
// expressions
|
||||
switch (GetId(node))
|
||||
{
|
||||
switch (GetId(node)) {
|
||||
case __sunConstants.EXPRESSION: return new sunExpression(location);
|
||||
case __sunConstants.OPERAND: return new sunOperand(location);
|
||||
case __sunConstants.TERM: return new sunNode(location);
|
||||
|
||||
|
||||
case __sunConstants.UNARY_OPERATOR_LIST: return new sunUnaryOperatorList(location);
|
||||
|
||||
case __sunConstants.INT_CAST: return new sunIntCast(location);
|
||||
|
@ -192,14 +169,12 @@ namespace arookas
|
|||
}
|
||||
|
||||
// builtins
|
||||
switch (GetId(node))
|
||||
{
|
||||
switch (GetId(node)) {
|
||||
case __sunConstants.BUILTIN_DECLARATION: return new sunBuiltinDeclaration(location);
|
||||
}
|
||||
|
||||
// functions
|
||||
switch (GetId(node))
|
||||
{
|
||||
switch (GetId(node)) {
|
||||
case __sunConstants.FUNCTION_DEFINITION: return new sunFunctionDefinition(location);
|
||||
case __sunConstants.FUNCTION_CALL: return new sunFunctionCall(location);
|
||||
|
||||
|
@ -210,8 +185,7 @@ namespace arookas
|
|||
}
|
||||
|
||||
// variables
|
||||
switch (GetId(node))
|
||||
{
|
||||
switch (GetId(node)) {
|
||||
case __sunConstants.VARIABLE_REFERENCE: return new sunStorableReference(location);
|
||||
case __sunConstants.VARIABLE_DECLARATION: return new sunVariableDeclaration(location);
|
||||
case __sunConstants.VARIABLE_DEFINITION: return new sunVariableDefinition(location);
|
||||
|
@ -220,14 +194,12 @@ namespace arookas
|
|||
}
|
||||
|
||||
// constants
|
||||
switch (GetId(node))
|
||||
{
|
||||
switch (GetId(node)) {
|
||||
case __sunConstants.CONST_DEFINITION: return new sunConstantDefinition(location);
|
||||
}
|
||||
|
||||
// flow control
|
||||
switch (GetId(node))
|
||||
{
|
||||
switch (GetId(node)) {
|
||||
case __sunConstants.IF_STATEMENT: return new sunIf(location);
|
||||
case __sunConstants.WHILE_STATEMENT: return new sunWhile(location);
|
||||
case __sunConstants.DO_STATEMENT: return new sunDo(location);
|
||||
|
@ -242,8 +214,7 @@ namespace arookas
|
|||
}
|
||||
|
||||
// cleanup keywords punctuation
|
||||
switch (GetId(node))
|
||||
{
|
||||
switch (GetId(node)) {
|
||||
// keywords
|
||||
case __sunConstants.IMPORT:
|
||||
case __sunConstants.BUILTIN:
|
||||
|
@ -286,22 +257,19 @@ namespace arookas
|
|||
case __sunConstants.COMMA:
|
||||
case __sunConstants.DOT:
|
||||
// case __sunConstants.ELLIPSIS: // do not exclude ellipsis for variadic parameters
|
||||
case __sunConstants.QMARK:
|
||||
{
|
||||
return null;
|
||||
}
|
||||
case __sunConstants.QMARK: {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
// emergency fallback
|
||||
return null;
|
||||
}
|
||||
static __sunConstants GetId(Node node)
|
||||
{
|
||||
static __sunConstants GetId(Node node) {
|
||||
return (__sunConstants)node.Id;
|
||||
}
|
||||
|
||||
public static bool IsKeyword(string name)
|
||||
{
|
||||
public static bool IsKeyword(string name) {
|
||||
return keywords.Contains(name);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,10 +2,8 @@
|
|||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
||||
namespace arookas
|
||||
{
|
||||
class sunScopeStack : IEnumerable<sunScope>
|
||||
{
|
||||
namespace arookas {
|
||||
class sunScopeStack : IEnumerable<sunScope> {
|
||||
List<sunScope> Stack { get; set; }
|
||||
|
||||
public int Count { get { return Stack.Count; } }
|
||||
|
@ -24,25 +22,20 @@ namespace arookas
|
|||
|
||||
public sunScope this[int index] { get { return Stack[index]; } }
|
||||
|
||||
public sunScopeStack()
|
||||
{
|
||||
public sunScopeStack() {
|
||||
Stack = new List<sunScope>(8);
|
||||
Push(sunScopeType.Script); // push global scope
|
||||
}
|
||||
|
||||
public void Push(sunScopeType type)
|
||||
{
|
||||
public void Push(sunScopeType type) {
|
||||
Stack.Add(new sunScope(type));
|
||||
}
|
||||
public void Pop()
|
||||
{
|
||||
if (Count > 1)
|
||||
{
|
||||
public void Pop() {
|
||||
if (Count > 1) {
|
||||
Stack.RemoveAt(Count - 1);
|
||||
}
|
||||
}
|
||||
public void Clear()
|
||||
{
|
||||
public void Clear() {
|
||||
Stack.Clear();
|
||||
Push(sunScopeType.Script); // add global scope
|
||||
}
|
||||
|
@ -52,36 +45,29 @@ namespace arookas
|
|||
public void ResetLocalCount() { LocalCount = 0; }
|
||||
#endif
|
||||
|
||||
public sunVariableSymbol DeclareVariable(string name)
|
||||
{
|
||||
switch (Top.Type)
|
||||
{
|
||||
public sunVariableSymbol DeclareVariable(string name) {
|
||||
switch (Top.Type) {
|
||||
case sunScopeType.Script: return DeclareGlobal(name);
|
||||
case sunScopeType.Function: return DeclareLocal(name);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
public sunConstantSymbol DeclareConstant(string name, sunExpression expression)
|
||||
{
|
||||
public sunConstantSymbol DeclareConstant(string name, sunExpression expression) {
|
||||
return Top.DeclareConstant(name, expression);
|
||||
}
|
||||
sunVariableSymbol DeclareGlobal(string name)
|
||||
{
|
||||
sunVariableSymbol DeclareGlobal(string name) {
|
||||
var symbol = Top.DeclareVariable(name, 0, GlobalCount);
|
||||
#if !SSC_PACK_VARS
|
||||
if (symbol != null)
|
||||
{
|
||||
if (symbol != null) {
|
||||
++GlobalCount;
|
||||
}
|
||||
#endif
|
||||
return symbol;
|
||||
}
|
||||
sunVariableSymbol DeclareLocal(string name)
|
||||
{
|
||||
sunVariableSymbol DeclareLocal(string name) {
|
||||
var symbol = Top.DeclareVariable(name, 1, LocalCount);
|
||||
#if !SSC_PACK_VARS
|
||||
if (symbol != null)
|
||||
{
|
||||
if (symbol != null) {
|
||||
++LocalCount;
|
||||
}
|
||||
#endif
|
||||
|
@ -92,15 +78,13 @@ namespace arookas
|
|||
IEnumerator IEnumerable.GetEnumerator() { return GetEnumerator(); }
|
||||
}
|
||||
|
||||
class sunScope
|
||||
{
|
||||
class sunScope {
|
||||
List<sunStorableSymbol> Storables { get; set; }
|
||||
IEnumerable<sunVariableSymbol> Variables { get { return Storables.OfType<sunVariableSymbol>(); } }
|
||||
IEnumerable<sunConstantSymbol> Constants { get { return Storables.OfType<sunConstantSymbol>(); } }
|
||||
public sunScopeType Type { get; private set; }
|
||||
|
||||
public sunScope(sunScopeType type)
|
||||
{
|
||||
public sunScope(sunScopeType type) {
|
||||
Storables = new List<sunStorableSymbol>(10);
|
||||
Type = type;
|
||||
}
|
||||
|
@ -111,20 +95,16 @@ namespace arookas
|
|||
|
||||
public bool GetIsDeclared(string name) { return Storables.Any(v => v.Name == name); }
|
||||
|
||||
public sunVariableSymbol DeclareVariable(string name, int display, int index)
|
||||
{
|
||||
if (GetIsDeclared(name))
|
||||
{
|
||||
public sunVariableSymbol DeclareVariable(string name, int display, int index) {
|
||||
if (GetIsDeclared(name)) {
|
||||
return null;
|
||||
}
|
||||
var symbol = new sunVariableSymbol(name, display, index);
|
||||
Storables.Add(symbol);
|
||||
return symbol;
|
||||
}
|
||||
public sunConstantSymbol DeclareConstant(string name, sunExpression expression)
|
||||
{
|
||||
if (GetIsDeclared(name))
|
||||
{
|
||||
public sunConstantSymbol DeclareConstant(string name, sunExpression expression) {
|
||||
if (GetIsDeclared(name)) {
|
||||
return null;
|
||||
}
|
||||
var symbol = new sunConstantSymbol(name, expression);
|
||||
|
@ -137,8 +117,7 @@ namespace arookas
|
|||
public sunConstantSymbol ResolveConstant(string name) { return Constants.FirstOrDefault(i => i.Name == name); }
|
||||
}
|
||||
|
||||
enum sunScopeType
|
||||
{
|
||||
enum sunScopeType {
|
||||
Script, // outside of a function
|
||||
Function, // inside of a function
|
||||
}
|
||||
|
|
|
@ -5,10 +5,8 @@ using System.Collections;
|
|||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
||||
namespace arookas
|
||||
{
|
||||
class sunSymbolTable : IEnumerable<sunSymbol>
|
||||
{
|
||||
namespace arookas {
|
||||
class sunSymbolTable : IEnumerable<sunSymbol> {
|
||||
List<sunSymbol> Symbols { get; set; }
|
||||
|
||||
public int Count { get { return Symbols.Count; } }
|
||||
|
@ -26,19 +24,16 @@ namespace arookas
|
|||
public IEnumerable<sunVariableSymbol> Variables { get { return Symbols.OfType<sunVariableSymbol>(); } }
|
||||
public IEnumerable<sunConstantSymbol> Constants { get { return Symbols.OfType<sunConstantSymbol>(); } }
|
||||
|
||||
public sunSymbolTable()
|
||||
{
|
||||
public sunSymbolTable() {
|
||||
Symbols = new List<sunSymbol>(10);
|
||||
}
|
||||
|
||||
public void Add(sunSymbol symbol) { Symbols.Add(symbol); }
|
||||
public void Clear() { Symbols.Clear(); }
|
||||
|
||||
public void Write(aBinaryWriter writer)
|
||||
{
|
||||
public void Write(aBinaryWriter writer) {
|
||||
int ofs = 0;
|
||||
foreach (var sym in this)
|
||||
{
|
||||
foreach (var sym in this) {
|
||||
writer.WriteS32((int)sym.Type);
|
||||
writer.WriteS32(ofs);
|
||||
writer.Write32(sym.Data);
|
||||
|
@ -49,8 +44,7 @@ namespace arookas
|
|||
|
||||
ofs += writer.Encoding.GetByteCount(sym.Name) + 1; // include null terminator
|
||||
}
|
||||
foreach (var sym in this)
|
||||
{
|
||||
foreach (var sym in this) {
|
||||
writer.WriteString(sym.Name, aBinaryStringFormat.NullTerminated);
|
||||
}
|
||||
}
|
||||
|
@ -59,32 +53,28 @@ namespace arookas
|
|||
IEnumerator IEnumerable.GetEnumerator() { return GetEnumerator(); }
|
||||
}
|
||||
|
||||
abstract class sunSymbol
|
||||
{
|
||||
abstract class sunSymbol {
|
||||
public string Name { get; private set; }
|
||||
|
||||
// symbol table
|
||||
public abstract sunSymbolType Type { get; }
|
||||
public abstract uint Data { get; }
|
||||
|
||||
protected sunSymbol(string name)
|
||||
{
|
||||
protected sunSymbol(string name) {
|
||||
Name = name;
|
||||
}
|
||||
|
||||
public abstract void Compile(sunContext context);
|
||||
}
|
||||
|
||||
abstract class sunCallableSymbol : sunSymbol
|
||||
{
|
||||
abstract class sunCallableSymbol : sunSymbol {
|
||||
public sunParameterInfo Parameters { get; private set; }
|
||||
protected List<sunPoint> CallSites { get; private set; }
|
||||
|
||||
public bool HasCallSites { get { return CallSites.Count > 0; } }
|
||||
|
||||
protected sunCallableSymbol(string name, sunParameterInfo parameterInfo)
|
||||
: base(name)
|
||||
{
|
||||
: base(name) {
|
||||
Parameters = parameterInfo;
|
||||
CallSites = new List<sunPoint>(10);
|
||||
}
|
||||
|
@ -93,8 +83,7 @@ namespace arookas
|
|||
public abstract void CloseCallSites(sunContext context);
|
||||
}
|
||||
|
||||
class sunBuiltinSymbol : sunCallableSymbol
|
||||
{
|
||||
class sunBuiltinSymbol : sunCallableSymbol {
|
||||
public int Index { get; private set; }
|
||||
|
||||
// symbol table
|
||||
|
@ -102,27 +91,20 @@ namespace arookas
|
|||
public override uint Data { get { return (uint)Index; } }
|
||||
|
||||
public sunBuiltinSymbol(string name, sunParameterInfo parameters, int index)
|
||||
: base(name, parameters)
|
||||
{
|
||||
: base(name, parameters) {
|
||||
Index = index;
|
||||
}
|
||||
|
||||
public override void Compile(sunContext context)
|
||||
{
|
||||
public override void Compile(sunContext context) {
|
||||
throw new InvalidOperationException("Cannot compile builtins.");
|
||||
}
|
||||
public override void OpenCallSite(sunContext context, int argumentCount)
|
||||
{
|
||||
public override void OpenCallSite(sunContext context, int argumentCount) {
|
||||
context.Text.CallBuiltin(Index, argumentCount);
|
||||
}
|
||||
public override void CloseCallSites(sunContext context)
|
||||
{
|
||||
// do nothing
|
||||
}
|
||||
public override void CloseCallSites(sunContext context) { }
|
||||
}
|
||||
|
||||
class sunFunctionSymbol : sunCallableSymbol
|
||||
{
|
||||
class sunFunctionSymbol : sunCallableSymbol {
|
||||
sunNode Body { get; set; }
|
||||
public uint Offset { get; private set; }
|
||||
|
||||
|
@ -131,18 +113,15 @@ namespace arookas
|
|||
public override uint Data { get { return (uint)Offset; } }
|
||||
|
||||
public sunFunctionSymbol(string name, sunParameterInfo parameters, sunNode body)
|
||||
: base(name, parameters)
|
||||
{
|
||||
: base(name, parameters) {
|
||||
Body = body;
|
||||
}
|
||||
|
||||
public override void Compile(sunContext context)
|
||||
{
|
||||
public override void Compile(sunContext context) {
|
||||
Offset = context.Text.Offset;
|
||||
context.Scopes.Push(sunScopeType.Function);
|
||||
context.Scopes.ResetLocalCount();
|
||||
foreach (var parameter in Parameters)
|
||||
{
|
||||
foreach (var parameter in Parameters) {
|
||||
context.Scopes.DeclareVariable(parameter); // since there is no AST node for these, they won't affect MaxLocalCount
|
||||
}
|
||||
context.Text.StoreDisplay(1);
|
||||
|
@ -151,46 +130,38 @@ namespace arookas
|
|||
context.Text.ReturnVoid();
|
||||
context.Scopes.Pop();
|
||||
}
|
||||
public override void OpenCallSite(sunContext context, int argumentCount)
|
||||
{
|
||||
public override void OpenCallSite(sunContext context, int argumentCount) {
|
||||
var point = context.Text.CallFunction(argumentCount);
|
||||
CallSites.Add(point);
|
||||
}
|
||||
public override void CloseCallSites(sunContext context)
|
||||
{
|
||||
foreach (var callSite in CallSites)
|
||||
{
|
||||
public override void CloseCallSites(sunContext context) {
|
||||
foreach (var callSite in CallSites) {
|
||||
context.Text.ClosePoint(callSite, Offset);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class sunParameterInfo : IEnumerable<string>
|
||||
{
|
||||
class sunParameterInfo : IEnumerable<string> {
|
||||
string[] Parameters { get; set; }
|
||||
public int Minimum { get { return Parameters.Length; } }
|
||||
public bool IsVariadic { get; private set; }
|
||||
|
||||
public sunParameterInfo(IEnumerable<sunIdentifier> parameters, bool variadic)
|
||||
{
|
||||
public sunParameterInfo(IEnumerable<sunIdentifier> parameters, bool variadic) {
|
||||
// validate parameter names
|
||||
var duplicate = parameters.FirstOrDefault(a => parameters.Count(b => a.Value == b.Value) > 1);
|
||||
if (duplicate != null)
|
||||
{
|
||||
if (duplicate != null) {
|
||||
throw new sunRedeclaredParameterException(duplicate);
|
||||
}
|
||||
Parameters = parameters.Select(i => i.Value).ToArray();
|
||||
IsVariadic = variadic;
|
||||
}
|
||||
public sunParameterInfo(IEnumerable<string> parameters, bool variadic)
|
||||
{
|
||||
public sunParameterInfo(IEnumerable<string> parameters, bool variadic) {
|
||||
// validate parameter names
|
||||
Parameters = parameters.ToArray();
|
||||
IsVariadic = variadic;
|
||||
}
|
||||
|
||||
public bool ValidateArgumentCount(int count)
|
||||
{
|
||||
public bool ValidateArgumentCount(int count) {
|
||||
return IsVariadic ? count >= Minimum : count == Minimum;
|
||||
}
|
||||
|
||||
|
@ -198,36 +169,26 @@ namespace arookas
|
|||
IEnumerator IEnumerable.GetEnumerator() { return GetEnumerator(); }
|
||||
}
|
||||
|
||||
abstract class sunStorableSymbol : sunSymbol
|
||||
{
|
||||
abstract class sunStorableSymbol : sunSymbol {
|
||||
protected sunStorableSymbol(string name)
|
||||
: base(name)
|
||||
{
|
||||
: base(name) { }
|
||||
|
||||
}
|
||||
|
||||
public override void Compile(sunContext context)
|
||||
{
|
||||
CompileGet(context); // compile get by default
|
||||
}
|
||||
public override void Compile(sunContext context) { CompileGet(context); } // compile get by default
|
||||
public abstract void CompileGet(sunContext context);
|
||||
public abstract void CompileSet(sunContext context);
|
||||
public virtual void CompileInc(sunContext context)
|
||||
{
|
||||
public virtual void CompileInc(sunContext context) {
|
||||
CompileGet(context);
|
||||
context.Text.PushInt(1);
|
||||
context.Text.Add();
|
||||
}
|
||||
public virtual void CompileDec(sunContext context)
|
||||
{
|
||||
public virtual void CompileDec(sunContext context) {
|
||||
CompileGet(context);
|
||||
context.Text.PushInt(1);
|
||||
context.Text.Sub();
|
||||
}
|
||||
}
|
||||
|
||||
class sunVariableSymbol : sunStorableSymbol
|
||||
{
|
||||
class sunVariableSymbol : sunStorableSymbol {
|
||||
public int Display { get; private set; }
|
||||
public int Index { get; private set; }
|
||||
|
||||
|
@ -236,32 +197,18 @@ namespace arookas
|
|||
public override uint Data { get { return (uint)Index; } }
|
||||
|
||||
public sunVariableSymbol(string name, int display, int index)
|
||||
: base(name)
|
||||
{
|
||||
: base(name) {
|
||||
Display = display;
|
||||
Index = index;
|
||||
}
|
||||
|
||||
public override void CompileGet(sunContext context)
|
||||
{
|
||||
context.Text.PushVariable(Display, Index);
|
||||
}
|
||||
public override void CompileSet(sunContext context)
|
||||
{
|
||||
context.Text.StoreVariable(Display, Index);
|
||||
}
|
||||
public override void CompileInc(sunContext context)
|
||||
{
|
||||
context.Text.IncVariable(Display, Index);
|
||||
}
|
||||
public override void CompileDec(sunContext context)
|
||||
{
|
||||
context.Text.DecVariable(Display, Index);
|
||||
}
|
||||
public override void CompileGet(sunContext context) { context.Text.PushVariable(Display, Index); }
|
||||
public override void CompileSet(sunContext context) { context.Text.StoreVariable(Display, Index); }
|
||||
public override void CompileInc(sunContext context) { context.Text.IncVariable(Display, Index); }
|
||||
public override void CompileDec(sunContext context) { context.Text.DecVariable(Display, Index); }
|
||||
}
|
||||
|
||||
class sunConstantSymbol : sunStorableSymbol
|
||||
{
|
||||
class sunConstantSymbol : sunStorableSymbol {
|
||||
sunExpression Expression { get; set; }
|
||||
|
||||
// symbol table
|
||||
|
@ -269,28 +216,23 @@ namespace arookas
|
|||
public override uint Data { get { return 0; } }
|
||||
|
||||
public sunConstantSymbol(string name, sunExpression expression)
|
||||
: base(name)
|
||||
{
|
||||
if (expression == null)
|
||||
{
|
||||
: base(name) {
|
||||
if (expression == null) {
|
||||
throw new ArgumentNullException("expression");
|
||||
}
|
||||
Expression = expression;
|
||||
}
|
||||
|
||||
public override void CompileGet(sunContext context)
|
||||
{
|
||||
public override void CompileGet(sunContext context) {
|
||||
Expression.Compile(context);
|
||||
}
|
||||
public override void CompileSet(sunContext context)
|
||||
{
|
||||
public override void CompileSet(sunContext context) {
|
||||
// checks against this have to be implemented at a higher level
|
||||
throw new InvalidOperationException();
|
||||
}
|
||||
}
|
||||
|
||||
enum sunSymbolType
|
||||
{
|
||||
enum sunSymbolType {
|
||||
Builtin,
|
||||
Function,
|
||||
Variable,
|
||||
|
|
104
ssc/writer.cs
104
ssc/writer.cs
|
@ -1,88 +1,59 @@
|
|||
using arookas.IO.Binary;
|
||||
|
||||
namespace arookas
|
||||
{
|
||||
class sunWriter
|
||||
{
|
||||
namespace arookas {
|
||||
class sunWriter {
|
||||
aBinaryWriter writer;
|
||||
|
||||
public uint Offset { get { return (uint)writer.Position; } }
|
||||
|
||||
public sunWriter(aBinaryWriter writer)
|
||||
{
|
||||
public sunWriter(aBinaryWriter writer) {
|
||||
this.writer = writer;
|
||||
}
|
||||
|
||||
public sunPoint OpenPoint() { return new sunPoint(Offset); }
|
||||
public void ClosePoint(sunPoint point)
|
||||
{
|
||||
ClosePoint(point, (uint)writer.Position);
|
||||
}
|
||||
public void ClosePoint(sunPoint point, uint offset)
|
||||
{
|
||||
public void ClosePoint(sunPoint point) { ClosePoint(point, (uint)writer.Position); }
|
||||
public void ClosePoint(sunPoint point, uint offset) {
|
||||
writer.Keep();
|
||||
writer.Goto(point.Offset);
|
||||
writer.Write32(offset);
|
||||
writer.Back();
|
||||
}
|
||||
|
||||
public void PushInt(int value)
|
||||
{
|
||||
switch (value) // shortcut commands
|
||||
{
|
||||
public void PushInt(int value) {
|
||||
switch (value) { // shortcut commands
|
||||
case 0: writer.Write8(0x25); return;
|
||||
case 1: writer.Write8(0x26); return;
|
||||
}
|
||||
writer.Write8(0x00);
|
||||
writer.WriteS32(value);
|
||||
}
|
||||
public void PushFloat(float value)
|
||||
{
|
||||
public void PushFloat(float value) {
|
||||
writer.Write8(0x01);
|
||||
writer.WriteF32(value);
|
||||
}
|
||||
public void PushData(int dataIndex)
|
||||
{
|
||||
public void PushData(int dataIndex) {
|
||||
writer.Write8(0x02);
|
||||
writer.WriteS32(dataIndex);
|
||||
}
|
||||
public void PushAddress(int value)
|
||||
{
|
||||
public void PushAddress(int value) {
|
||||
writer.Write8(0x03);
|
||||
writer.WriteS32(value);
|
||||
}
|
||||
public void PushVariable(sunVariableSymbol variableInfo)
|
||||
{
|
||||
PushVariable(variableInfo.Display, variableInfo.Index);
|
||||
}
|
||||
public void PushVariable(int display, int variableIndex)
|
||||
{
|
||||
public void PushVariable(sunVariableSymbol variableInfo) { PushVariable(variableInfo.Display, variableInfo.Index); }
|
||||
public void PushVariable(int display, int variableIndex) {
|
||||
writer.Write8(0x04);
|
||||
writer.WriteS32(display);
|
||||
writer.WriteS32(variableIndex);
|
||||
}
|
||||
|
||||
public void Nop()
|
||||
{
|
||||
writer.Write8(0x05);
|
||||
}
|
||||
|
||||
public void IncVariable(sunVariableSymbol variableInfo)
|
||||
{
|
||||
IncVariable(variableInfo.Display, variableInfo.Index);
|
||||
}
|
||||
public void DecVariable(sunVariableSymbol variableInfo)
|
||||
{
|
||||
DecVariable(variableInfo.Display, variableInfo.Index);
|
||||
}
|
||||
public void IncVariable(int display, int variableIndex)
|
||||
{
|
||||
public void Nop() { writer.Write8(0x05); }
|
||||
public void IncVariable(sunVariableSymbol variableInfo) { IncVariable(variableInfo.Display, variableInfo.Index); }
|
||||
public void DecVariable(sunVariableSymbol variableInfo) { DecVariable(variableInfo.Display, variableInfo.Index); }
|
||||
public void IncVariable(int display, int variableIndex) {
|
||||
writer.Write8(0x06);
|
||||
writer.WriteS32(display);
|
||||
writer.WriteS32(variableIndex);
|
||||
}
|
||||
public void DecVariable(int display, int variableIndex)
|
||||
{
|
||||
public void DecVariable(int display, int variableIndex) {
|
||||
writer.Write8(0x07);
|
||||
writer.WriteS32(display);
|
||||
writer.WriteS32(variableIndex);
|
||||
|
@ -94,12 +65,8 @@ namespace arookas
|
|||
public void Div() { writer.Write8(0x0B); }
|
||||
public void Mod() { writer.Write8(0x0C); }
|
||||
|
||||
public void StoreVariable(sunVariableSymbol variableInfo)
|
||||
{
|
||||
StoreVariable(variableInfo.Display, variableInfo.Index);
|
||||
}
|
||||
public void StoreVariable(int display, int variableIndex)
|
||||
{
|
||||
public void StoreVariable(sunVariableSymbol variableInfo) { StoreVariable(variableInfo.Display, variableInfo.Index); }
|
||||
public void StoreVariable(int display, int variableIndex) {
|
||||
writer.Write8(0x0D);
|
||||
writer.Write8(0x04); // unused (skipped over by TSpcInterp)
|
||||
writer.WriteS32(display);
|
||||
|
@ -121,34 +88,29 @@ namespace arookas
|
|||
public void ShL() { writer.Write8(0x1A); }
|
||||
public void ShR() { writer.Write8(0x1B); }
|
||||
|
||||
public sunPoint CallFunction(int argumentCount)
|
||||
{
|
||||
public sunPoint CallFunction(int argumentCount) {
|
||||
writer.Write8(0x1C);
|
||||
sunPoint point = OpenPoint();
|
||||
writer.Write32(0); // dummy
|
||||
writer.WriteS32(argumentCount);
|
||||
return point;
|
||||
}
|
||||
public void CallFunction(sunPoint point, int argumentCount)
|
||||
{
|
||||
public void CallFunction(sunPoint point, int argumentCount) {
|
||||
writer.Write8(0x1C);
|
||||
writer.Write32(point.Offset);
|
||||
writer.WriteS32(argumentCount);
|
||||
}
|
||||
public void CallBuiltin(int symbolIndex, int argumentCount)
|
||||
{
|
||||
public void CallBuiltin(int symbolIndex, int argumentCount) {
|
||||
writer.Write8(0x1D);
|
||||
writer.WriteS32(symbolIndex);
|
||||
writer.WriteS32(argumentCount);
|
||||
}
|
||||
|
||||
public void DeclareLocal(int count)
|
||||
{
|
||||
public void DeclareLocal(int count) {
|
||||
writer.Write8(0x1E);
|
||||
writer.WriteS32(count);
|
||||
}
|
||||
public void StoreDisplay(int display)
|
||||
{
|
||||
public void StoreDisplay(int display) {
|
||||
writer.Write8(0x1F);
|
||||
writer.WriteS32(display);
|
||||
}
|
||||
|
@ -156,27 +118,23 @@ namespace arookas
|
|||
public void ReturnValue() { writer.Write8(0x20); }
|
||||
public void ReturnVoid() { writer.Write8(0x21); }
|
||||
|
||||
public sunPoint GotoIfZero()
|
||||
{
|
||||
public sunPoint GotoIfZero() {
|
||||
writer.Write8(0x22);
|
||||
sunPoint point = OpenPoint();
|
||||
writer.Write32(0); // dummy
|
||||
return point;
|
||||
}
|
||||
public sunPoint Goto()
|
||||
{
|
||||
public sunPoint Goto() {
|
||||
writer.Write8(0x23);
|
||||
sunPoint point = OpenPoint();
|
||||
writer.Write32(0); // dummy
|
||||
return point;
|
||||
}
|
||||
public void GotoIfZero(sunPoint point)
|
||||
{
|
||||
public void GotoIfZero(sunPoint point) {
|
||||
writer.Write8(0x22);
|
||||
writer.Write32(point.Offset);
|
||||
}
|
||||
public void Goto(sunPoint point)
|
||||
{
|
||||
public void Goto(sunPoint point) {
|
||||
writer.Write8(0x23);
|
||||
writer.Write32(point.Offset);
|
||||
}
|
||||
|
@ -185,13 +143,11 @@ namespace arookas
|
|||
public void Terminate() { writer.Write8(0x27); }
|
||||
}
|
||||
|
||||
struct sunPoint
|
||||
{
|
||||
struct sunPoint {
|
||||
readonly uint offset;
|
||||
public uint Offset { get { return offset; } }
|
||||
|
||||
public sunPoint(uint offset)
|
||||
{
|
||||
public sunPoint(uint offset) {
|
||||
this.offset = offset;
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue