Added expression analysis.
Also gave the AST cast nodes a base class while I was at it.
This commit is contained in:
parent
6be1779781
commit
54bd3618e3
5 changed files with 108 additions and 28 deletions
|
@ -1,9 +1,14 @@
|
||||||
using System.Collections;
|
using System;
|
||||||
|
using System.Collections;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
|
||||||
namespace arookas {
|
namespace arookas {
|
||||||
class sunExpression : sunNode {
|
interface sunTerm {
|
||||||
|
sunExpressionFlags GetExpressionFlags(sunContext context);
|
||||||
|
}
|
||||||
|
|
||||||
|
class sunExpression : sunNode, sunTerm {
|
||||||
public sunExpression(sunSourceLocation location)
|
public sunExpression(sunSourceLocation location)
|
||||||
: base(location) { }
|
: base(location) { }
|
||||||
|
|
||||||
|
@ -11,8 +16,11 @@ namespace arookas {
|
||||||
Stack<sunOperator> operatorStack = new Stack<sunOperator>(32);
|
Stack<sunOperator> operatorStack = new Stack<sunOperator>(32);
|
||||||
CompileExpression(context, this, operatorStack);
|
CompileExpression(context, this, operatorStack);
|
||||||
}
|
}
|
||||||
|
public sunExpressionFlags Analyze(sunContext context) {
|
||||||
|
return AnalyzeExpression(context, this);
|
||||||
|
}
|
||||||
|
|
||||||
void CompileExpression(sunContext context, sunExpression expression, Stack<sunOperator> operatorStack) {
|
static void CompileExpression(sunContext context, sunExpression expression, Stack<sunOperator> operatorStack) {
|
||||||
// this implementation assumes that the expression production child list alternates between operand and operator
|
// 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
|
// we can safely assume this as the grammar "operand {binary_operator operand}" enforces it
|
||||||
int stackCount = operatorStack.Count;
|
int stackCount = operatorStack.Count;
|
||||||
|
@ -47,6 +55,35 @@ namespace arookas {
|
||||||
operatorStack.Pop().Compile(context);
|
operatorStack.Pop().Compile(context);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
static sunExpressionFlags AnalyzeExpression(sunContext context, sunExpression expression) {
|
||||||
|
sunExpressionFlags flags = sunExpressionFlags.None;
|
||||||
|
foreach (var operand in expression.OfType<sunOperand>()) {
|
||||||
|
var term = operand.Term as sunTerm;
|
||||||
|
if (term != null) {
|
||||||
|
flags |= term.GetExpressionFlags(context);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return flags;
|
||||||
|
}
|
||||||
|
|
||||||
|
sunExpressionFlags sunTerm.GetExpressionFlags(sunContext context) {
|
||||||
|
return Analyze(context);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[Flags]
|
||||||
|
enum sunExpressionFlags {
|
||||||
|
// contents
|
||||||
|
None = 0,
|
||||||
|
Literals = 1,
|
||||||
|
Variables = 2,
|
||||||
|
Augments = 4,
|
||||||
|
Casts = 8,
|
||||||
|
Calls = 16,
|
||||||
|
Constants = 32,
|
||||||
|
|
||||||
|
// description
|
||||||
|
Dynamic = 64,
|
||||||
}
|
}
|
||||||
|
|
||||||
class sunOperand : sunNode {
|
class sunOperand : sunNode {
|
||||||
|
@ -71,7 +108,7 @@ namespace arookas {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class sunTernaryOperator : sunNode {
|
class sunTernaryOperator : sunNode, sunTerm {
|
||||||
public sunExpression Condition { get { return this[0] as sunExpression; } }
|
public sunExpression Condition { get { return this[0] as sunExpression; } }
|
||||||
public sunExpression TrueBody { get { return this[1] as sunExpression; } }
|
public sunExpression TrueBody { get { return this[1] as sunExpression; } }
|
||||||
public sunExpression FalseBody { get { return this[2] as sunExpression; } }
|
public sunExpression FalseBody { get { return this[2] as sunExpression; } }
|
||||||
|
@ -88,10 +125,14 @@ namespace arookas {
|
||||||
FalseBody.Compile(context);
|
FalseBody.Compile(context);
|
||||||
context.Text.ClosePoint(trueEpilogue);
|
context.Text.ClosePoint(trueEpilogue);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
sunExpressionFlags sunTerm.GetExpressionFlags(sunContext context) {
|
||||||
|
return Condition.Analyze(context) | TrueBody.Analyze(context) | FalseBody.Analyze(context);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// increment/decrement
|
// increment/decrement
|
||||||
class sunPostfixAugment : sunOperand {
|
class sunPostfixAugment : sunOperand, sunTerm {
|
||||||
public sunIdentifier Variable { get { return this[0] as sunIdentifier; } }
|
public sunIdentifier Variable { get { return this[0] as sunIdentifier; } }
|
||||||
public sunAugment Augment { get { return this[1] as sunAugment; } }
|
public sunAugment Augment { get { return this[1] as sunAugment; } }
|
||||||
|
|
||||||
|
@ -108,9 +149,13 @@ namespace arookas {
|
||||||
}
|
}
|
||||||
Augment.Compile(context, symbol);
|
Augment.Compile(context, symbol);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
sunExpressionFlags sunTerm.GetExpressionFlags(sunContext context) {
|
||||||
|
return sunExpressionFlags.Augments;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class sunPrefixAugment : sunOperand {
|
class sunPrefixAugment : sunOperand, sunTerm {
|
||||||
public sunAugment Augment { get { return this[0] as sunAugment; } }
|
public sunAugment Augment { get { return this[0] as sunAugment; } }
|
||||||
public sunIdentifier Variable { get { return this[1] as sunIdentifier; } }
|
public sunIdentifier Variable { get { return this[1] as sunIdentifier; } }
|
||||||
|
|
||||||
|
@ -127,6 +172,10 @@ namespace arookas {
|
||||||
symbol.CompileGet(context);
|
symbol.CompileGet(context);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
sunExpressionFlags sunTerm.GetExpressionFlags(sunContext context) {
|
||||||
|
return sunExpressionFlags.Augments;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
abstract class sunAugment : sunNode {
|
abstract class sunAugment : sunNode {
|
||||||
|
|
|
@ -27,7 +27,7 @@ namespace arookas {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class sunFunctionCall : sunNode {
|
class sunFunctionCall : sunNode, sunTerm {
|
||||||
public sunIdentifier Function { get { return this[0] as sunIdentifier; } }
|
public sunIdentifier Function { get { return this[0] as sunIdentifier; } }
|
||||||
public sunNode Arguments { get { return this[1] as sunNode; } }
|
public sunNode Arguments { get { return this[1] as sunNode; } }
|
||||||
|
|
||||||
|
@ -47,6 +47,10 @@ namespace arookas {
|
||||||
context.Text.Pop();
|
context.Text.Pop();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
sunExpressionFlags sunTerm.GetExpressionFlags(sunContext context) {
|
||||||
|
return sunExpressionFlags.Calls | sunExpressionFlags.Dynamic;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class sunParameterList : sunNode {
|
class sunParameterList : sunNode {
|
||||||
|
|
|
@ -3,7 +3,7 @@ using System.Globalization;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
|
|
||||||
namespace arookas {
|
namespace arookas {
|
||||||
class sunIntLiteral : sunToken<int> { // base-10 integer
|
class sunIntLiteral : sunToken<int>, sunTerm { // base-10 integer
|
||||||
public sunIntLiteral(sunSourceLocation location, string literal)
|
public sunIntLiteral(sunSourceLocation location, string literal)
|
||||||
: base(location) {
|
: base(location) {
|
||||||
Value = Int32.Parse(literal);
|
Value = Int32.Parse(literal);
|
||||||
|
@ -14,6 +14,10 @@ namespace arookas {
|
||||||
: base(location) { }
|
: base(location) { }
|
||||||
|
|
||||||
public override void Compile(sunContext context) { context.Text.PushInt(Value); }
|
public override void Compile(sunContext context) { context.Text.PushInt(Value); }
|
||||||
|
|
||||||
|
sunExpressionFlags sunTerm.GetExpressionFlags(sunContext context) {
|
||||||
|
return sunExpressionFlags.Literals;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class sunHexLiteral : sunIntLiteral { // base-16 integer
|
class sunHexLiteral : sunIntLiteral { // base-16 integer
|
||||||
|
@ -31,7 +35,7 @@ namespace arookas {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class sunFloatLiteral : sunToken<float> {
|
class sunFloatLiteral : sunToken<float>, sunTerm {
|
||||||
public sunFloatLiteral(sunSourceLocation location, string literal)
|
public sunFloatLiteral(sunSourceLocation location, string literal)
|
||||||
: base(location) {
|
: base(location) {
|
||||||
Value = Single.Parse(literal);
|
Value = Single.Parse(literal);
|
||||||
|
@ -40,9 +44,13 @@ namespace arookas {
|
||||||
public override void Compile(sunContext context) {
|
public override void Compile(sunContext context) {
|
||||||
context.Text.PushFloat(Value);
|
context.Text.PushFloat(Value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
sunExpressionFlags sunTerm.GetExpressionFlags(sunContext context) {
|
||||||
|
return sunExpressionFlags.Literals;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class sunStringLiteral : sunToken<string> {
|
class sunStringLiteral : sunToken<string>, sunTerm {
|
||||||
public sunStringLiteral(sunSourceLocation location, string literal)
|
public sunStringLiteral(sunSourceLocation location, string literal)
|
||||||
: base(location) {
|
: base(location) {
|
||||||
Value = UnescapeString(literal.Substring(1, literal.Length - 2)); // remove enclosing quotes
|
Value = UnescapeString(literal.Substring(1, literal.Length - 2)); // remove enclosing quotes
|
||||||
|
@ -123,6 +131,10 @@ namespace arookas {
|
||||||
(c >= 'A' && c <= 'F') ||
|
(c >= 'A' && c <= 'F') ||
|
||||||
(c >= 'a' && c <= 'f');
|
(c >= 'a' && c <= 'f');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
sunExpressionFlags sunTerm.GetExpressionFlags(sunContext context) {
|
||||||
|
return sunExpressionFlags.Literals;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class sunIdentifier : sunToken<string> {
|
class sunIdentifier : sunToken<string> {
|
||||||
|
|
|
@ -54,42 +54,46 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class sunIntCast : sunNode {
|
abstract class sunCast : sunNode, sunTerm {
|
||||||
public sunExpression Argument { get { return this[0] as sunExpression; } }
|
public sunExpression Argument { get { return this[0] as sunExpression; } }
|
||||||
|
|
||||||
|
protected sunCast(sunSourceLocation location)
|
||||||
|
: base(location) { }
|
||||||
|
|
||||||
|
protected void Compile(sunContext context, sunBuiltinSymbol symbol) {
|
||||||
|
Argument.Compile(context);
|
||||||
|
context.Text.CallBuiltin(symbol.Index, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
sunExpressionFlags sunTerm.GetExpressionFlags(sunContext context) {
|
||||||
|
return sunExpressionFlags.Casts | Argument.Analyze(context);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class sunIntCast : sunCast {
|
||||||
public sunIntCast(sunSourceLocation location)
|
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");
|
Compile(context, context.ResolveSystemBuiltin("int"));
|
||||||
Argument.Compile(context);
|
|
||||||
context.Text.CallBuiltin(builtinInfo.Index, 1);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class sunFloatCast : sunNode {
|
class sunFloatCast : sunCast {
|
||||||
public sunExpression Argument { get { return this[0] as sunExpression; } }
|
|
||||||
|
|
||||||
public sunFloatCast(sunSourceLocation location)
|
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");
|
Compile(context, context.ResolveSystemBuiltin("float"));
|
||||||
Argument.Compile(context);
|
|
||||||
context.Text.CallBuiltin(builtinInfo.Index, 1);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class sunTypeofCast : sunNode {
|
class sunTypeofCast : sunCast {
|
||||||
public sunExpression Argument { get { return this[0] as sunExpression; } }
|
|
||||||
|
|
||||||
public sunTypeofCast(sunSourceLocation location)
|
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");
|
Compile(context, context.ResolveSystemBuiltin("typeof"));
|
||||||
Argument.Compile(context);
|
|
||||||
context.Text.CallBuiltin(builtinInfo.Index, 1);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
namespace arookas {
|
namespace arookas {
|
||||||
class sunStorableReference : sunNode {
|
class sunStorableReference : sunNode, sunTerm {
|
||||||
public sunIdentifier Storable { get { return this[0] as sunIdentifier; } }
|
public sunIdentifier Storable { get { return this[0] as sunIdentifier; } }
|
||||||
|
|
||||||
public sunStorableReference(sunSourceLocation location)
|
public sunStorableReference(sunSourceLocation location)
|
||||||
|
@ -8,6 +8,17 @@
|
||||||
public override void Compile(sunContext context) {
|
public override void Compile(sunContext context) {
|
||||||
context.MustResolveStorable(Storable).Compile(context);
|
context.MustResolveStorable(Storable).Compile(context);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
sunExpressionFlags sunTerm.GetExpressionFlags(sunContext context) {
|
||||||
|
var symbol = context.MustResolveStorable(Storable);
|
||||||
|
if (symbol is sunVariableSymbol) {
|
||||||
|
return sunExpressionFlags.Variables | sunExpressionFlags.Dynamic;
|
||||||
|
}
|
||||||
|
else if (symbol is sunConstantSymbol) {
|
||||||
|
return sunExpressionFlags.Constants;
|
||||||
|
}
|
||||||
|
return sunExpressionFlags.None;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class sunVariableDeclaration : sunNode {
|
class sunVariableDeclaration : sunNode {
|
||||||
|
|
Loading…
Add table
Reference in a new issue