public static bool TryCreateConstant( CompilerTarget target, ISourcePosition position, PValue value, out AstExpr expr) { expr = null; if (value.Type is ObjectPType) target.Loader.Options.ParentEngine.CreateNativePValue(value.Value); if (value.Type is IntPType || value.Type is RealPType || value.Type is BoolPType || value.Type is StringPType || value.Type is NullPType || _isModuleName(value)) expr = new AstConstant(position.File, position.Line, position.Column, value.Value); else //Cannot represent value in a constant instruction return false; return true; }
private static AstExpr _genCompare(MacroContext context, AstExpr retVar, ReturnVariant expected) { var inv = context.Invocation; AstExpr expectedNode = new AstConstant(inv.File, inv.Line, inv.Column, (int) expected); return context.Factory.BinaryOperation(inv.Position, retVar, BinaryOperator.Equality, expectedNode); }
private static void _replaceDebug(CompilerTarget t, IList<AstNode> block, bool debugging) { for (var i = 0; i < block.Count; i++) { var stmt = block[i] as AstGetSet; //look for calls if (_isDebugCall(stmt)) { System.Diagnostics.Debug.Assert(stmt != null); //Found a call to debug block.RemoveAt(i); if (debugging) { for (var j = 0; j < stmt.Arguments.Count; j++) { var arg = stmt.Arguments[j] as AstIndirectCall; AstReference refNode; if (arg != null && (refNode = arg.Subject as AstReference) != null) { var printlnCall = t.Factory.Call(stmt.Position, EntityRef.Command.Create(Engine.PrintLineAlias)); var concatCall = t.Factory.Call(stmt.Position, EntityRef.Command.Create(Engine.ConcatenateAlias)); var consts = new AstConstant( stmt.File, stmt.Line, stmt.Column, String.Concat("DEBUG ", refNode.Entity, " = ")); concatCall.Arguments.Add(consts); concatCall.Arguments.Add(arg); printlnCall.Arguments.Add(concatCall); block.Insert(i, printlnCall); i += 1; } //end if arg not null } //end for arguments } //end if debugging continue; } //end if debug call var cond = block[i] as AstCondition; //look for conditions if (cond != null) { var expr = cond.Condition as AstIndirectCall; AstReference refNode; EntityRef.Command cmd; if (expr != null && (refNode = expr.Subject as AstReference) != null && refNode.Entity.TryGetCommand(out cmd) && Engine.StringsAreEqual(cmd.Id,Engine.DebugAlias) ) cond.Condition = new AstConstant(expr.File, expr.Line, expr.Column, debugging); } //Recursively replace 'debug' in nested blocks. var complex = block[i] as IAstHasBlocks; if (complex != null) foreach (var subBlock in complex.Blocks) _replaceDebug(t, subBlock, debugging); } //end for statements }
private bool _tryOptimizeConstCast(CompilerTarget target, AstConstant constSubject, AstConstantTypeExpression constType, out AstExpr expr) { expr = null; PType type; try { type = target.Loader.ConstructPType(constType.TypeExpression); } catch (PrexoniteException) { //ignore, cast failed. cannot be optimized return false; } PValue result; if (constSubject.ToPValue(target).TryConvertTo(target.Loader, type, out result)) return AstConstant.TryCreateConstant(target, Position, result, out expr); else return false; }
public override bool TryOptimize(CompilerTarget target, out AstExpr expr) { expr = null; var placeholders = Conditions.Count(AstPartiallyApplicable.IsPlaceholder); for (var node = Conditions.First; node != null; node = node.Next) { var condition = node.Value; _OptimizeNode(target, ref condition); node.Value = condition; //Update list of conditions with optimized condition PValue resultP; if (condition is AstConstant && ((AstConstant) condition).ToPValue(target).TryConvertTo(target.Loader, PType.Bool, false, out resultP)) { if ((bool) resultP.Value == ShortcircuitValue) { // Expr1 OP shortcircuit OP Expr2 = shortcircuit // Expr1 OP shortcircuit OP Expr2 OP ? = const(shortcircuit) var shortcircuitConst = new AstConstant(condition.File, condition.Line, condition.Column, ShortcircuitValue); if (placeholders > 0) { if (!Conditions.Last.Value.IsPlaceholder() || placeholders > 1) _reportInvalidPlaceholders(target); expr = shortcircuitConst.ConstFunc(); } else { expr = shortcircuitConst; } return true; } else { // Expr1 OP ¬shortcircuit OP Expr2 = Expr1 OP Expr2 Conditions.Remove(node); } } else if (condition is AstPlaceholder) { placeholders++; } } if (Conditions.Count == 0) { expr = new AstConstant(File, Line, Column, !ShortcircuitValue); } else if (Conditions.Count == 1) { var primaryExpr = Conditions.First.Value; expr = _GetOptimizedNode(target, new AstTypecast(primaryExpr.File, primaryExpr.Line, primaryExpr.Column, primaryExpr, new AstConstantTypeExpression(primaryExpr.File, primaryExpr.Line, primaryExpr.Column, PType.Bool.ToString()))); } return expr != null; }
private static bool _parseArguments(MacroContext context, out AstExpr call, out AstExpr justEffect, out AstExpr[] args, out AstExpr macroSpec) { /* call(macroRef,...) = call([],macroRef,[false],...); * call([],macroRef,[je],...) = call([],macroRef,[je,context.Call],...); * call([],macroRef,[je,c],...) = { macroId := macroRef.Id; * macroInterpretation := interpretation(macroRef); * call := c; * justEffect := je * } * call([proto(...1)],...2) = call([],from_proto(proto),[false,PCall.Get],[...1],...2); * call([proto(...1) = x],...2) = call([],from_proto(proto),[false,PCall.Set],[...1],...2,[x]); * call([proto(...1),je],...2) = call([],from_proto(proto),[je,PCall.Get],[...1],...2); * call([proto(...1) = x,je],...2) = call([],from_proto(proto),[je,PCall.Set],[...1],...2,[x]); * call([proto(...1),je,c],...2) = call([],from_proto(proto),[je,c],[...1],...2); */ var inv = context.Invocation; justEffect = new AstConstant(inv.File, inv.Line, inv.Column, false); call = PCall.Get.ToExpr(context.Invocation.Position); var invokeSpec = inv.Arguments[0]; var listSpec = invokeSpec as AstListLiteral; if (listSpec == null) { // - Macro reference specified as expression that evaluates to an actual macro reference args = inv.Arguments.Skip(1).ToArray(); macroSpec = invokeSpec; return _parseReference(context, inv.Arguments[0]); } else if (listSpec.Elements.Count == 0) { // - Macro reference specified as expression that evaluates to an actual macro reference // - followed by a list of options AstListLiteral optionsRaw; if (inv.Arguments.Count < 3 || (optionsRaw = inv.Arguments[2] as AstListLiteral) == null) { _errorUsageFullRef(context); args = null; macroSpec = null; return false; } macroSpec = inv.Arguments[1]; //first option: justEffect if (optionsRaw.Elements.Count >= 1) justEffect = optionsRaw.Elements[0]; //second option: call type if (optionsRaw.Elements.Count >= 2) call = optionsRaw.Elements[1]; //args: except first 3 args = inv.Arguments.Skip(3).ToArray(); return _parseReference(context, inv.Arguments[1]); } else { // - Macro reference specified as a prototype // - includes list of options var specProto = listSpec.Elements[0]; PCall protoCall; IList<AstExpr> protoArguments; if ( !_parsePrototype(context, specProto, out protoCall, out protoArguments, out macroSpec)) { args = null; return false; } //first option: justEffect if (listSpec.Elements.Count >= 2) justEffect = listSpec.Elements[1]; //second option: call type call = listSpec.Elements.Count >= 3 ? listSpec.Elements[2] : protoCall.ToExpr(specProto.Position); //args: lift and pass prototype arguments, special care for set var setArgs = protoCall == PCall.Set ? protoArguments.Last() : null; var getArgs = protoCall == PCall.Set ? protoArguments.Take(protoArguments.Count - 1) : protoArguments; // ReSharper disable PossibleMultipleEnumeration // enumerating getArgs multiple times is safe and efficient if (getArgs.Any(a => !_ensureExplicitPlaceholder(context, a))) { args = new AstExpr[] {}; return false; } IEnumerable<AstExpr> getArgsLit; if (getArgs.Any()) { var getArgsLitNode = new AstListLiteral(specProto.File, specProto.Line, specProto.Column); getArgsLitNode.Elements.AddRange(getArgs); getArgsLit = getArgsLitNode.Singleton(); } // ReSharper restore PossibleMultipleEnumeration else { getArgsLit = Enumerable.Empty<AstExpr>(); } IEnumerable<AstExpr> setArgsLit; if (setArgs != null) { if (!_ensureExplicitPlaceholder(context, setArgs)) { args = new AstExpr[] {}; return false; } var lit = new AstListLiteral(setArgs.File, setArgs.Line, setArgs.Column); lit.Elements.Add(setArgs); setArgsLit = lit.Singleton(); } else { setArgsLit = Enumerable.Empty<AstExpr>(); } args = getArgsLit .Append(inv.Arguments.Skip(1)) .Append(setArgsLit).ToArray(); return true; } }
public override bool TryOptimize(CompilerTarget target, out AstExpr expr) { _OptimizeNode(target, ref _subject); _type = (AstTypeExpr) _GetOptimizedNode(target, _type); expr = null; var constSubject = _subject as AstConstant; var constType = _type as AstConstantTypeExpression; if (constSubject == null || constType == null) return false; PType type; try { type = target.Loader.ConstructPType(constType.TypeExpression); } catch (PrexoniteException) { //ignore, cast failed. cannot be optimized return false; } expr = new AstConstant(File, Line, Column, constSubject.ToPValue(target).Type.Equals(type)); return true; }