Added expression analysis.

Also gave the AST cast nodes a base class while I was at it.
This commit is contained in:
arookas 2015-12-28 14:22:54 -05:00
parent 6be1779781
commit 54bd3618e3
5 changed files with 108 additions and 28 deletions

View file

@ -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 {

View file

@ -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 {

View file

@ -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> {

View file

@ -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);
} }
} }

View file

@ -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 {