diff --git a/ssc/ast/nodes.expressions.cs b/ssc/ast/nodes.expressions.cs index 188e29e..a71d106 100644 --- a/ssc/ast/nodes.expressions.cs +++ b/ssc/ast/nodes.expressions.cs @@ -1,9 +1,14 @@ -using System.Collections; +using System; +using System.Collections; using System.Collections.Generic; using System.Linq; namespace arookas { - class sunExpression : sunNode { + interface sunTerm { + sunExpressionFlags GetExpressionFlags(sunContext context); + } + + class sunExpression : sunNode, sunTerm { public sunExpression(sunSourceLocation location) : base(location) { } @@ -11,8 +16,11 @@ namespace arookas { Stack<sunOperator> operatorStack = new Stack<sunOperator>(32); 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 // we can safely assume this as the grammar "operand {binary_operator operand}" enforces it int stackCount = operatorStack.Count; @@ -47,6 +55,35 @@ namespace arookas { 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 { @@ -71,7 +108,7 @@ namespace arookas { } } - class sunTernaryOperator : sunNode { + class sunTernaryOperator : sunNode, sunTerm { 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; } } @@ -88,10 +125,14 @@ namespace arookas { FalseBody.Compile(context); context.Text.ClosePoint(trueEpilogue); } + + sunExpressionFlags sunTerm.GetExpressionFlags(sunContext context) { + return Condition.Analyze(context) | TrueBody.Analyze(context) | FalseBody.Analyze(context); + } } - + // increment/decrement - class sunPostfixAugment : sunOperand { + class sunPostfixAugment : sunOperand, sunTerm { public sunIdentifier Variable { get { return this[0] as sunIdentifier; } } public sunAugment Augment { get { return this[1] as sunAugment; } } @@ -108,9 +149,13 @@ namespace arookas { } 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 sunIdentifier Variable { get { return this[1] as sunIdentifier; } } @@ -127,6 +172,10 @@ namespace arookas { symbol.CompileGet(context); } } + + sunExpressionFlags sunTerm.GetExpressionFlags(sunContext context) { + return sunExpressionFlags.Augments; + } } abstract class sunAugment : sunNode { diff --git a/ssc/ast/nodes.functions.cs b/ssc/ast/nodes.functions.cs index 80c7caf..2c230c9 100644 --- a/ssc/ast/nodes.functions.cs +++ b/ssc/ast/nodes.functions.cs @@ -27,7 +27,7 @@ namespace arookas { } } - class sunFunctionCall : sunNode { + class sunFunctionCall : sunNode, sunTerm { public sunIdentifier Function { get { return this[0] as sunIdentifier; } } public sunNode Arguments { get { return this[1] as sunNode; } } @@ -47,6 +47,10 @@ namespace arookas { context.Text.Pop(); } } + + sunExpressionFlags sunTerm.GetExpressionFlags(sunContext context) { + return sunExpressionFlags.Calls | sunExpressionFlags.Dynamic; + } } class sunParameterList : sunNode { diff --git a/ssc/ast/nodes.literals.cs b/ssc/ast/nodes.literals.cs index 0e51cc7..a2693d4 100644 --- a/ssc/ast/nodes.literals.cs +++ b/ssc/ast/nodes.literals.cs @@ -3,7 +3,7 @@ using System.Globalization; using System.Text; namespace arookas { - class sunIntLiteral : sunToken<int> { // base-10 integer + class sunIntLiteral : sunToken<int>, sunTerm { // base-10 integer public sunIntLiteral(sunSourceLocation location, string literal) : base(location) { Value = Int32.Parse(literal); @@ -14,6 +14,10 @@ namespace arookas { : base(location) { } public override void Compile(sunContext context) { context.Text.PushInt(Value); } + + sunExpressionFlags sunTerm.GetExpressionFlags(sunContext context) { + return sunExpressionFlags.Literals; + } } 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) : base(location) { Value = Single.Parse(literal); @@ -40,9 +44,13 @@ namespace arookas { public override void Compile(sunContext context) { 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) : base(location) { 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'); } + + sunExpressionFlags sunTerm.GetExpressionFlags(sunContext context) { + return sunExpressionFlags.Literals; + } } class sunIdentifier : sunToken<string> { diff --git a/ssc/ast/nodes.system.cs b/ssc/ast/nodes.system.cs index 705db09..04f3d9a 100644 --- a/ssc/ast/nodes.system.cs +++ b/ssc/ast/nodes.system.cs @@ -54,42 +54,46 @@ } } - class sunIntCast : sunNode { + abstract class sunCast : sunNode, sunTerm { 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) : base(location) { } public override void Compile(sunContext context) { - var builtinInfo = context.ResolveSystemBuiltin("int"); - Argument.Compile(context); - context.Text.CallBuiltin(builtinInfo.Index, 1); + Compile(context, context.ResolveSystemBuiltin("int")); } } - class sunFloatCast : sunNode { - public sunExpression Argument { get { return this[0] as sunExpression; } } - + class sunFloatCast : sunCast { public sunFloatCast(sunSourceLocation location) : base(location) { } public override void Compile(sunContext context) { - var builtinInfo = context.ResolveSystemBuiltin("float"); - Argument.Compile(context); - context.Text.CallBuiltin(builtinInfo.Index, 1); + Compile(context, context.ResolveSystemBuiltin("float")); } } - class sunTypeofCast : sunNode { - public sunExpression Argument { get { return this[0] as sunExpression; } } - + class sunTypeofCast : sunCast { public sunTypeofCast(sunSourceLocation location) : base(location) { } public override void Compile(sunContext context) { - var builtinInfo = context.ResolveSystemBuiltin("typeof"); - Argument.Compile(context); - context.Text.CallBuiltin(builtinInfo.Index, 1); + Compile(context, context.ResolveSystemBuiltin("typeof")); } } diff --git a/ssc/ast/nodes.variables.cs b/ssc/ast/nodes.variables.cs index 5e9f6ee..2610150 100644 --- a/ssc/ast/nodes.variables.cs +++ b/ssc/ast/nodes.variables.cs @@ -1,5 +1,5 @@ namespace arookas { - class sunStorableReference : sunNode { + class sunStorableReference : sunNode, sunTerm { public sunIdentifier Storable { get { return this[0] as sunIdentifier; } } public sunStorableReference(sunSourceLocation location) @@ -8,6 +8,17 @@ public override void Compile(sunContext 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 {