public void add_jump_unoptimized(Opcode op, BasicBlock first) { Opcodes.Add(op); if (Dead == 2) return; do_add_jump(first); }
public bool is_declared(string name, Opcode.Sigil sigil) { var glob = SymbolTable.GetGlob(this, name, false); // TODO implement imported check, and setting imported // flag in assignment return false; }
public StackFrame(string pack, string file, int l, P5Code code, Opcode.ContextValues cxt, bool eval) { Package = pack; File = file; Line = l; Code = code; Context = cxt; IsEval = eval; }
public static IP5Any DoFile(Runtime runtime, Opcode.ContextValues context, P5Scalar file) { var file_s = file.AsString(runtime); var ret = LoadFile(runtime, context, file_s); if (ret == null) return new P5Scalar(runtime); return ret; }
public static IP5Any LoadFile(Runtime runtime, Opcode.ContextValues context, string file) { IP5Any ret = null; foreach (var loader in runtime.ModuleLoaders) { ret = loader.TryLoad(runtime, context, file); if (ret != null) return ret; } return ret; }
// TODO generate from Perl code public void add_jump(Opcode op, BasicBlock first) { if (Opcodes.Count == 0 && Predecessors.Count > 0 && first != this) { while (first.Successors.Count > 0 && first.Opcodes.Count == 0) first = first.Successors[0]; var pred = new List<BasicBlock>(Predecessors); foreach (var p in pred) p._change_successor(this, first); add_successor(first); } else add_jump_unoptimized(op, first); }
public static IP5Any RequireFile(Runtime runtime, Opcode.ContextValues context, P5Scalar file) { if (file.IsInteger(runtime) || file.IsFloat(runtime)) { var value = file.AsFloat(runtime); var version = runtime.SymbolTable.GetScalar(runtime, "]", false); var version_f = version.AsFloat(runtime); if (version_f >= value) return new P5Scalar(runtime, true); var msg = string.Format("Perl {0:F} required--this is only {1:F} stopped.", value, version_f); throw new P5Exception(runtime, msg); } var file_s = file.AsString(runtime); var inc = runtime.SymbolTable.GetHash(runtime, "INC", true); if (inc.ExistsKey(runtime, file_s)) return new P5Scalar(runtime, 1); var ret = LoadFile(runtime, context, file_s); if (ret == null) { var message = new System.Text.StringBuilder(); var inc_a = runtime.SymbolTable.GetArray(runtime, "INC", true); message.Append(string.Format("Can't locate {0:S} in @INC (@INC contains:", file_s)); foreach (var dir in inc_a) { message.Append(" "); message.Append(dir.AsString(runtime)); } message.Append(")"); throw new P5Exception(runtime, message.ToString()); } return ret; }
public IP5Value get_symbol(string name, Opcode.Sigil sigil) { switch (sigil) { case Opcode.Sigil.SCALAR: return SymbolTable.GetScalar(this, name, false); case Opcode.Sigil.ARRAY: return SymbolTable.GetArray(this, name, false); case Opcode.Sigil.HASH: return SymbolTable.GetHash(this, name, false); case Opcode.Sigil.SUB: return SymbolTable.GetCode(this, name, false); case Opcode.Sigil.GLOB: return SymbolTable.GetGlob(this, name, false); case Opcode.Sigil.HANDLE: return SymbolTable.GetHandle(this, name, false); default: return null; } }
private Expression MakeNonFlatArray(Subroutine sub, Type type, Opcode op) { var data = new List<Expression>(); var temp = Expression.Variable(typeof(List<IP5Any>)); var method = typeof(List<IP5Any>).GetMethod("Add"); data.Add( Expression.Assign( temp, Expression.New( typeof(List<IP5Any>).GetConstructor(ProtoInt), Expression.Constant(op.Childs.Length)))); foreach (var i in op.Childs) data.Add( Expression.Call(temp, method, Generate(sub, i))); data.Add( Expression.New( type.GetConstructor( new Type[] { typeof(Runtime), typeof(List<IP5Any>) }), Runtime, temp)); return Expression.Block( type, new ParameterExpression[] { temp }, data); }
protected abstract Expression ScalarAssign(Subroutine sub, Opcode.ContextValues cxt, Expression lvalue, Expression rvalue);
protected abstract Expression StringRelOperator(Subroutine sub, Opcode op, ExpressionType operation);
public IP5Any TryLoad(Runtime runtime, Opcode.ContextValues context, string file) { var path = Builtins.SearchFile(runtime, file); if (path == null) return null; P5Code mod; if (path.EndsWith(".pb")) { var cu = Serializer.ReadCompilationUnit(runtime, path); mod = new DynamicGenerator(runtime).GenerateAndLoad(cu); } else { var parser = runtime.parser; mod = parser.ParseFile(runtime, path, false); } var ret = mod.Call(runtime, context, null); var inc = runtime.SymbolTable.GetHash(runtime, "INC", true); inc.SetItem(runtime, file, new P5Scalar(runtime, path)); return ret; }
public IP5Any TryLoad(Runtime runtime, Opcode.ContextValues context, string file) { System.Type module = assembly.GetType(file); if (module == null) return null; object main_sub = module.GetMethod("InitModule") .Invoke(null, new object[] { runtime }); P5Code main = main_sub as P5Code; var res = main.Call(runtime, context, null); var inc = runtime.SymbolTable.GetHash(runtime, "INC", true); inc.SetItem(runtime, file, new P5Scalar(runtime, module.FullName)); return res; }
protected string MethodForSlot(Opcode.Sigil slot) { switch (slot) { case Opcode.Sigil.SCALAR: return "GetScalar"; case Opcode.Sigil.ARRAY: return "GetArray"; case Opcode.Sigil.HASH: return "GetHash"; case Opcode.Sigil.STASH: return "GetStash"; case Opcode.Sigil.SUB: return "GetCode"; case Opcode.Sigil.GLOB: return "GetGlob"; case Opcode.Sigil.HANDLE: return "GetHandle"; default: throw new System.Exception(string.Format("Unhandled slot {0:D}", slot)); } }
public P5ArrayAssignmentBinder(Runtime runtime, Opcode.ContextValues cxt, bool common) { Runtime = runtime; Context = cxt; Common = common; }
public static IP5Any HashEach(Runtime runtime, Opcode.ContextValues cxt, P5Hash hash) { P5Scalar key, value; if (hash.NextKey(runtime, out key, out value)) { if (cxt == Opcode.ContextValues.SCALAR) return key; else return new P5List(runtime, key, value); } else { if (cxt == Opcode.ContextValues.SCALAR) return new P5Scalar(runtime); else return new P5List(runtime); } }
public static IP5Any Reverse(Runtime runtime, Opcode.ContextValues context, P5Array args) { if (context == Opcode.ContextValues.LIST) return args.Reversed(runtime); int count = args.GetCount(runtime); char[] value; if (count == 0) value = runtime.SymbolTable.GetStashScalar(runtime, "_", true).AsString(runtime).ToCharArray(); else if (count == 1) value = args.GetItem(runtime, 0).AsString(runtime).ToCharArray(); else { var t = new System.Text.StringBuilder(); foreach (var i in args) t.Append(i.AsString(runtime)); value = t.ToString().ToCharArray(); } // TODO does not handle UCS-4 System.Array.Reverse(value); return new P5Scalar(runtime, new string(value)); }
private Expression MakeFlatArray(Subroutine sub, Type type, Opcode op) { var data = new List<Expression>(); var temp = Expression.Variable(type); var method = type.GetMethod("PushFlatten"); data.Add( Expression.Assign( temp, Expression.New( type.GetConstructor(ProtoRuntimeInt), Runtime, Expression.Constant(op.Childs.Length)))); foreach (var i in op.Childs) data.Add( Expression.Call(temp, method, Runtime, Generate(sub, i))); data.Add(temp); return Expression.Block( type, new ParameterExpression[] { temp }, data); }
private Expression GetLexicalValue(int index, Opcode.Sigil slot) { var lex = GetLexical(index, slot); var type = TypeForSlot(slot); // the condition is necessary because a jump might bypass // a declaration; if the subroutine does not contain any goto, or // if the goto inizializes all jumped-over variables, then the // condition can be removed return Expression.Condition( Expression.NotEqual( lex, Expression.Constant(null, type)), lex, Expression.Assign( lex, Expression.New( type.GetConstructor(ProtoRuntime), Runtime))); }
private Expression GetLexical(int index, Opcode.Sigil slot) { return GetLexical(index, TypeForSlot(slot)); }
protected abstract Expression UnaryOperator(Subroutine sub, Opcode op, ExpressionType operation);
protected abstract Expression UnaryIncrement(Subroutine sub, Opcode op, ExpressionType operation);
public static IP5Any Return(Runtime runtime, Opcode.ContextValues cxt, IP5Any value) { if (cxt == Opcode.ContextValues.SCALAR) return value.AsScalar(runtime); if (cxt == Opcode.ContextValues.LIST) return value as P5Array ?? new P5List(runtime, value); return P5List.EmptyList; }
private Expression OpContext(Opcode op) { if (op.Context == (int)Opcode.ContextValues.CALLER) return Context; else return Expression.Constant( (Opcode.ContextValues)op.Context, typeof(Opcode.ContextValues)); }
public static P5Scalar WantArray(Runtime runtime, Opcode.ContextValues cxt) { if (cxt == Opcode.ContextValues.VOID) return new P5Scalar(runtime); return new P5Scalar(runtime, cxt == Opcode.ContextValues.LIST); }
private string PropertyForSlot(Opcode.Sigil slot) { switch (slot) { case Opcode.Sigil.SCALAR: return "Scalar"; case Opcode.Sigil.ARRAY: return "Array"; case Opcode.Sigil.HASH: return "Hash"; case Opcode.Sigil.SUB: return "Code"; case Opcode.Sigil.HANDLE: return "Handle"; default: throw new System.Exception(string.Format("Unhandled slot {0:D}", slot)); } }
public IP5Any MatchGlobal(Runtime runtime, IP5Any value, int flags, Opcode.ContextValues cxt, ref RxResult oldState) { return P5Regex.MatchGlobalHelper(this, runtime, value, flags, cxt, ref oldState); }
public Expression Generate(Subroutine sub, Opcode op) { switch(op.Number) { case Opcode.OpNumber.OP_FRESH_STRING: case Opcode.OpNumber.OP_CONSTANT_STRING: { var cs = (ConstantString)op; return Expression.New( typeof(P5Scalar).GetConstructor(ProtoRuntimeString), new Expression[] { Runtime, Expression.Constant(cs.Value) }); } case Opcode.OpNumber.OP_CONSTANT_UNDEF: { var ctor = typeof(P5Scalar).GetConstructor(ProtoRuntime); return Expression.New(ctor, new Expression[] { Runtime }); } case Opcode.OpNumber.OP_CONSTANT_INTEGER: return ConstantInteger(((ConstantInt)op).Value); case Opcode.OpNumber.OP_CONSTANT_FLOAT: return ConstantFloat(((ConstantFloat)op).Value); case Opcode.OpNumber.OP_CONSTANT_SUB: { var cs = (ConstantSub)op; return ConstantSub(cs.Value); } case Opcode.OpNumber.OP_UNDEF: { return Expression.Call( Generate(sub, op.Childs[0]), typeof(IP5Any).GetMethod("Undef"), Runtime); } case Opcode.OpNumber.OP_GLOBAL: { Global gop = (Global)op; bool create; if (gop.Slot == Opcode.Sigil.STASH) create = (gop.Context & (int)Opcode.ContextValues.NOCREATE) == 0; else create = true; var global = AccessGlobal(Runtime, gop.Slot, gop.Name, create); if (create) return global; else return UndefIfNull(global); } case Opcode.OpNumber.OP_GLOB_SLOT: { GlobSlot gop = (GlobSlot)op; string name = PropertyForSlot(gop.Slot); return Expression.Property( Expression.Convert( Generate(sub, op.Childs[0]), typeof(P5Typeglob)), name); } case Opcode.OpNumber.OP_SWAP_GLOB_SLOT_SET: { GlobSlot gop = (GlobSlot)op; string name = PropertyForSlot(gop.Slot); var property = Expression.Property( Expression.Convert( Generate(sub, op.Childs[1]), typeof(P5Typeglob)), name); return Expression.Assign( property, Expression.Convert( Generate(sub, op.Childs[0]), property.Type)); } case Opcode.OpNumber.OP_MAKE_LIST: { if ((op.Context & (int)Opcode.ContextValues.LVALUE) != 0) return MakeNonFlatArray(sub, typeof(P5LvalueList), op); else return MakeFlatArray(sub, typeof(P5List), op); } case Opcode.OpNumber.OP_MAKE_ARRAY: return MakeFlatArray(sub, typeof(P5Array), op); case Opcode.OpNumber.OP_DOT_DOT: { // TODO needs to handle the flip/flop mode in scalar context return Expression.Call( typeof(Builtins).GetMethod("MakeRange"), Runtime, Generate(sub, op.Childs[0]), Generate(sub, op.Childs[1])); } case Opcode.OpNumber.OP_ANONYMOUS_ARRAY: return Expression.Call( typeof(Builtins).GetMethod("AnonymousArray"), Runtime, Generate(sub, op.Childs[0])); case Opcode.OpNumber.OP_ANONYMOUS_HASH: return Expression.Call( typeof(Builtins).GetMethod("AnonymousHash"), Runtime, Generate(sub, op.Childs[0])); case Opcode.OpNumber.OP_PRINT: { Expression handle = Generate(sub, op.Childs[0]); if (handle.Type != typeof(P5Handle)) handle = Expression.Call( handle, typeof(IP5Any).GetMethod("DereferenceHandle"), Runtime); return Expression.Call( typeof(Builtins).GetMethod("Print"), Runtime, handle, Generate(sub, op.Childs[1])); } case Opcode.OpNumber.OP_READLINE: { return Expression.Call( typeof(Builtins).GetMethod("Readline"), Runtime, Expression.Call( Generate(sub, op.Childs[0]), typeof(IP5Any).GetMethod("DereferenceHandle"), Runtime), OpContext(op)); } case Opcode.OpNumber.OP_END: { return Expression.Return( SubLabel, Expression.Constant(null, typeof(IP5Any)), typeof(IP5Any)); } case Opcode.OpNumber.OP_STOP: { // TODO remove STOP return Generate(sub, op.Childs[0]); } case Opcode.OpNumber.OP_DIE: { return Expression.Block( Expression.Throw( Expression.Call( typeof(Builtins).GetMethod("Die"), Runtime, Generate(sub, op.Childs[0]))), // this is only to trick the type checker into // thinking that this is a "normal" expression Expression.Constant(null, typeof(IP5Any))); } case Opcode.OpNumber.OP_WARN: { return Expression.Call( typeof(Builtins).GetMethod("Warn"), Runtime, Generate(sub, op.Childs[0])); } case Opcode.OpNumber.OP_SPRINTF: { return Expression.Call( typeof(Builtins).GetMethod("Sprintf"), Runtime, Generate(sub, op.Childs[0])); } case Opcode.OpNumber.OP_DO_FILE: { return Expression.Call( typeof(Builtins).GetMethod("DoFile"), Runtime, OpContext(op), Generate(sub, op.Childs[0])); } case Opcode.OpNumber.OP_REQUIRE_FILE: { return Expression.Call( typeof(Builtins).GetMethod("RequireFile"), Runtime, OpContext(op), Generate(sub, op.Childs[0])); } case Opcode.OpNumber.OP_WANTARRAY: { return Expression.Call( typeof(Builtins).GetMethod("WantArray"), Runtime, Context); } case Opcode.OpNumber.OP_SCALAR: { return Expression.Call( Generate(sub, op.Childs[0]), typeof(IP5Any).GetMethod("AsScalar"), Runtime); } case Opcode.OpNumber.OP_RETURN: return ReturnExpression(Generate(sub, op.Childs[0])); case Opcode.OpNumber.OP_DYNAMIC_GOTO: { // TODO handle goto $LABEL var exit_scope = new List<Expression>(); var value = Expression.Parameter(typeof(P5Code)); var code = Expression.Call( Generate(sub, op.Childs[0]), typeof(IP5Any).GetMethod("DereferenceSubroutine"), Runtime); exit_scope.Add( Expression.Assign(value, code)); for (var s = CurrentScope; s != null; s = s.Outer != -1 ? sub.Scopes[s.Outer] : null) for (int j = s.Opcodes.Count - 1; j >= 0; --j) GenerateOpcodes(sub, s.Opcodes[j], exit_scope); exit_scope.Add( Expression.Call( Expression.Field(Runtime, "CallStack"), typeof(Stack<StackFrame>).GetMethod("Pop"))); // TODO this is not a real tail call: the .Net stack grows exit_scope.Add( ReturnExpression( Expression.Call( value, typeof(P5Code).GetMethod("Call"), Runtime, Context, Arguments))); return Expression.Block(typeof(IP5Any), new[] { value }, exit_scope); } case Opcode.OpNumber.OP_ASSIGN_LIST: { var lvalue = Generate(sub, op.Childs[1]); var rvalue = Generate(sub, op.Childs[0]); bool common = ((ListAssign)op).Common != 0; return ArrayAssign(sub, (Opcode.ContextValues)op.Context, lvalue, rvalue, common); } case Opcode.OpNumber.OP_SWAP_ASSIGN_LIST: { var lvalue = Generate(sub, op.Childs[0]); var rvalue = Generate(sub, op.Childs[1]); bool common = ((ListAssign)op).Common != 0; return ArrayAssign(sub, (Opcode.ContextValues)op.Context, lvalue, rvalue, common); } case Opcode.OpNumber.OP_ASSIGN: { var lvalue = Generate(sub, op.Childs[1]); var rvalue = Generate(sub, op.Childs[0]); return ScalarAssign(sub, (Opcode.ContextValues)op.Context, lvalue, rvalue); } case Opcode.OpNumber.OP_SWAP_ASSIGN: { var lvalue = Generate(sub, op.Childs[0]); var rvalue = Generate(sub, op.Childs[1]); return ScalarAssign(sub, (Opcode.ContextValues)op.Context, lvalue, rvalue); } case Opcode.OpNumber.OP_GET: { GetSet gs = (GetSet)op; return GetVariable(gs.Index, TypeForSlot(gs.Slot)); } case Opcode.OpNumber.OP_SET: { GetSet gs = (GetSet)op; var e = Generate(sub, op.Childs[0]); return Expression.Assign( GetVariable(gs.Index, TypeForSlot(gs.Slot)), e); } case Opcode.OpNumber.OP_JUMP: return Expression.Goto(BlockLabels[((Jump)op).To], typeof(IP5Any)); case Opcode.OpNumber.OP_JUMP_IF_NULL: { Expression cmp = Expression.Equal( Generate(sub, op.Childs[0]), Expression.Constant(null, typeof(object))); Expression jump = Expression.Goto( BlockLabels[((CondJump)op).To], typeof(IP5Any)); return Expression.IfThen(cmp, jump); } case Opcode.OpNumber.OP_JUMP_IF_S_EQ: { return GenerateJump(sub, op, "AsString", ExpressionType.Equal); } case Opcode.OpNumber.OP_JUMP_IF_S_NE: { return GenerateJump(sub, op, "AsString", ExpressionType.NotEqual); } case Opcode.OpNumber.OP_JUMP_IF_F_EQ: { return GenerateJump(sub, op, "AsFloat", ExpressionType.Equal); } case Opcode.OpNumber.OP_JUMP_IF_F_NE: { return GenerateJump(sub, op, "AsFloat", ExpressionType.NotEqual); } case Opcode.OpNumber.OP_JUMP_IF_F_GE: { return GenerateJump(sub, op, "AsFloat", ExpressionType.GreaterThanOrEqual); } case Opcode.OpNumber.OP_JUMP_IF_F_LE: { return GenerateJump(sub, op, "AsFloat", ExpressionType.LessThanOrEqual); } case Opcode.OpNumber.OP_JUMP_IF_F_GT: { return GenerateJump(sub, op, "AsFloat", ExpressionType.GreaterThan); } case Opcode.OpNumber.OP_JUMP_IF_F_LT: { return GenerateJump(sub, op, "AsFloat", ExpressionType.LessThan); } case Opcode.OpNumber.OP_JUMP_IF_TRUE: { Expression cmp = Expression.Call( Generate(sub, op.Childs[0]), typeof(IP5Any).GetMethod("AsBoolean"), Runtime); Expression jump = Expression.Goto( BlockLabels[((CondJump)op).To], typeof(IP5Any)); return Expression.IfThen(cmp, jump); } case Opcode.OpNumber.OP_LOG_NOT: return UnaryOperator(sub, op, ExpressionType.Not); case Opcode.OpNumber.OP_MINUS: return UnaryOperator(sub, op, ExpressionType.Negate); case Opcode.OpNumber.OP_DEFINED: return Defined(sub, op); case Opcode.OpNumber.OP_ORD: return Expression.Call( typeof(Builtins).GetMethod("Ord"), Runtime, Generate(sub, op.Childs[0])); case Opcode.OpNumber.OP_CHR: return Expression.Call( typeof(Builtins).GetMethod("Chr"), Runtime, Generate(sub, op.Childs[0])); case Opcode.OpNumber.OP_UC: return Expression.Call( typeof(Builtins).GetMethod("Uppercase"), Runtime, Generate(sub, op.Childs[0])); case Opcode.OpNumber.OP_LC: return Expression.Call( typeof(Builtins).GetMethod("Lowercase"), Runtime, Generate(sub, op.Childs[0])); case Opcode.OpNumber.OP_OCT: return Expression.Call( typeof(Builtins).GetMethod("Oct"), Runtime, Generate(sub, op.Childs[0])); case Opcode.OpNumber.OP_HEX: return Expression.Call( typeof(Builtins).GetMethod("Hex"), Runtime, Generate(sub, op.Childs[0])); case Opcode.OpNumber.OP_INDEX: { Expression start; if (op.Childs.Length == 3) start = Expression.Call( Generate(sub, op.Childs[2]), typeof(IP5Any).GetMethod("AsInteger"), Runtime); else start = Expression.Constant(0); return Expression.Call( typeof(Builtins).GetMethod("Index"), Runtime, Generate(sub, op.Childs[0]), Generate(sub, op.Childs[1]), start); } case Opcode.OpNumber.OP_CONCATENATE: { Expression s1 = Expression.Call(Generate(sub, op.Childs[0]), typeof(IP5Any).GetMethod("AsString"), Runtime); Expression s2 = Expression.Call(Generate(sub, op.Childs[1]), typeof(IP5Any).GetMethod("AsString"), Runtime); return Expression.New( typeof(P5Scalar).GetConstructor(ProtoRuntimeString), Runtime, Expression.Call( typeof(string).GetMethod("Concat", ProtoStringString), s1, s2)); } case Opcode.OpNumber.OP_CONCATENATE_ASSIGN: { return Expression.Call( Expression.Convert( Generate(sub, op.Childs[0]), typeof(P5Scalar)), typeof(P5Scalar).GetMethod("ConcatAssign"), Runtime, Generate(sub, op.Childs[1])); } case Opcode.OpNumber.OP_ARRAY_LENGTH: { Expression len = Expression.Call( Expression.Convert( Generate(sub, op.Childs[0]), typeof(IP5Array)), typeof(IP5Array).GetMethod("GetCount"), Runtime); Expression len_1 = Expression.Subtract(len, Expression.Constant(1)); return Expression.New( typeof(P5Scalar).GetConstructor(ProtoRuntimeInt), new Expression[] { Runtime, len_1 }); } case Opcode.OpNumber.OP_BIT_NOT: return UnaryOperator(sub, op, ExpressionType.OnesComplement); case Opcode.OpNumber.OP_BIT_OR: return BinaryOperator(sub, op, ExpressionType.Or); case Opcode.OpNumber.OP_BIT_OR_ASSIGN: return BinaryOperator(sub, op, ExpressionType.OrAssign); case Opcode.OpNumber.OP_BIT_AND: return BinaryOperator(sub, op, ExpressionType.And); case Opcode.OpNumber.OP_BIT_AND_ASSIGN: return BinaryOperator(sub, op, ExpressionType.AndAssign); case Opcode.OpNumber.OP_BIT_XOR: return BinaryOperator(sub, op, ExpressionType.ExclusiveOr); case Opcode.OpNumber.OP_BIT_XOR_ASSIGN: return BinaryOperator(sub, op, ExpressionType.ExclusiveOrAssign); case Opcode.OpNumber.OP_NUM_LE: return NumericRelOperator(sub, op, ExpressionType.LessThanOrEqual); case Opcode.OpNumber.OP_NUM_LT: return NumericRelOperator(sub, op, ExpressionType.LessThan); case Opcode.OpNumber.OP_NUM_EQ: return NumericRelOperator(sub, op, ExpressionType.Equal); case Opcode.OpNumber.OP_NUM_NE: return NumericRelOperator(sub, op, ExpressionType.NotEqual); case Opcode.OpNumber.OP_NUM_GE: return NumericRelOperator(sub, op, ExpressionType.GreaterThanOrEqual); case Opcode.OpNumber.OP_NUM_GT: return NumericRelOperator(sub, op, ExpressionType.GreaterThan); case Opcode.OpNumber.OP_STR_LE: return StringRelOperator(sub, op, ExpressionType.LessThanOrEqual); case Opcode.OpNumber.OP_STR_LT: return StringRelOperator(sub, op, ExpressionType.LessThan); case Opcode.OpNumber.OP_STR_EQ: return StringRelOperator(sub, op, ExpressionType.Equal); case Opcode.OpNumber.OP_STR_NE: return StringRelOperator(sub, op, ExpressionType.NotEqual); case Opcode.OpNumber.OP_STR_GE: return StringRelOperator(sub, op, ExpressionType.GreaterThanOrEqual); case Opcode.OpNumber.OP_STR_GT: return StringRelOperator(sub, op, ExpressionType.GreaterThan); case Opcode.OpNumber.OP_ADD: return BinaryOperator(sub, op, ExpressionType.Add); case Opcode.OpNumber.OP_ADD_ASSIGN: return BinaryOperator(sub, op, ExpressionType.AddAssign); case Opcode.OpNumber.OP_SUBTRACT: return BinaryOperator(sub, op, ExpressionType.Subtract); case Opcode.OpNumber.OP_SUBTRACT_ASSIGN: return BinaryOperator(sub, op, ExpressionType.SubtractAssign); case Opcode.OpNumber.OP_MULTIPLY: return BinaryOperator(sub, op, ExpressionType.Multiply); case Opcode.OpNumber.OP_MULTIPLY_ASSIGN: return BinaryOperator(sub, op, ExpressionType.MultiplyAssign); case Opcode.OpNumber.OP_DIVIDE: return BinaryOperator(sub, op, ExpressionType.Divide); case Opcode.OpNumber.OP_DIVIDE_ASSIGN: return BinaryOperator(sub, op, ExpressionType.DivideAssign); case Opcode.OpNumber.OP_SHIFT_LEFT: return BinaryOperator(sub, op, ExpressionType.LeftShift); case Opcode.OpNumber.OP_SHIFT_LEFT_ASSIGN: return BinaryOperator(sub, op, ExpressionType.LeftShiftAssign); case Opcode.OpNumber.OP_SHIFT_RIGHT: return BinaryOperator(sub, op, ExpressionType.RightShift); case Opcode.OpNumber.OP_SHIFT_RIGHT_ASSIGN: return BinaryOperator(sub, op, ExpressionType.RightShiftAssign); case Opcode.OpNumber.OP_PREINC: return UnaryIncrement(sub, op, ExpressionType.PreIncrementAssign); case Opcode.OpNumber.OP_PREDEC: return UnaryIncrement(sub, op, ExpressionType.PreDecrementAssign); case Opcode.OpNumber.OP_POSTINC: return UnaryIncrement(sub, op, ExpressionType.PostIncrementAssign); case Opcode.OpNumber.OP_POSTDEC: return UnaryIncrement(sub, op, ExpressionType.PostDecrementAssign); case Opcode.OpNumber.OP_REVERSE: return Expression.Call( typeof(Builtins).GetMethod("Reverse"), Runtime, OpContext(op), Generate(sub, op.Childs[0])); case Opcode.OpNumber.OP_REPEAT_ARRAY: return Expression.Call( Generate(sub, op.Childs[0]), typeof(P5Array).GetMethod("Repeat"), Runtime, Generate(sub, op.Childs[1])); case Opcode.OpNumber.OP_REPEAT_SCALAR: return Expression.Call( Expression.Call( Generate(sub, op.Childs[0]), typeof(IP5Any).GetMethod("AsScalar"), Runtime), typeof(P5Scalar).GetMethod("Repeat"), Runtime, Generate(sub, op.Childs[1])); case Opcode.OpNumber.OP_SORT: return Expression.Call( Generate(sub, op.Childs[0]), typeof(P5Array).GetMethod("Sort"), Runtime); case Opcode.OpNumber.OP_ARRAY_ELEMENT: { var ea = (ElementAccess)op; return Expression.Call( Generate(sub, op.Childs[0]), typeof(IP5Array).GetMethod("GetItemOrUndef"), Runtime, Generate(sub, op.Childs[1]), Expression.Constant(ea.Create != 0)); } case Opcode.OpNumber.OP_HASH_ELEMENT: { var ea = (ElementAccess)op; return Expression.Call( Generate(sub, op.Childs[0]), typeof(P5Hash).GetMethod("GetItemOrUndef"), Runtime, Generate(sub, op.Childs[1]), Expression.Constant(ea.Create != 0)); } case Opcode.OpNumber.OP_DELETE_HASH: { return Expression.Call( Generate(sub, op.Childs[0]), typeof(P5Hash).GetMethod("Delete"), Runtime, Generate(sub, op.Childs[1])); } case Opcode.OpNumber.OP_EXISTS_ARRAY: { return Expression.Call( Generate(sub, op.Childs[0]), typeof(P5Array).GetMethod("Exists"), Runtime, Generate(sub, op.Childs[1])); } case Opcode.OpNumber.OP_EXISTS_HASH: { return Expression.Call( Generate(sub, op.Childs[0]), typeof(P5Hash).GetMethod("Exists"), Runtime, Generate(sub, op.Childs[1])); } case Opcode.OpNumber.OP_PUSH_ELEMENT: { return Expression.Call( Generate(sub, op.Childs[0]), typeof(IP5Array).GetMethod("PushFlatten"), Runtime, Generate(sub, op.Childs[1])); } case Opcode.OpNumber.OP_ARRAY_PUSH: { return Expression.Call( Generate(sub, op.Childs[0]), typeof(IP5Array).GetMethod("PushList"), Runtime, Generate(sub, op.Childs[1])); } case Opcode.OpNumber.OP_ARRAY_UNSHIFT: { return Expression.Call( Generate(sub, op.Childs[0]), typeof(IP5Array).GetMethod("UnshiftList"), Runtime, Generate(sub, op.Childs[1])); } case Opcode.OpNumber.OP_ARRAY_POP: { return Expression.Call( Generate(sub, op.Childs[0]), typeof(IP5Array).GetMethod("PopElement"), Runtime); } case Opcode.OpNumber.OP_ARRAY_SHIFT: { return Expression.Call( Generate(sub, op.Childs[0]), typeof(IP5Array).GetMethod("ShiftElement"), Runtime); } case Opcode.OpNumber.OP_QUOTEMETA: { return Expression.Call( typeof(Builtins).GetMethod("QuoteMeta"), Runtime, Generate(sub, op.Childs[0])); } case Opcode.OpNumber.OP_STRINGIFY: { return Expression.New( typeof(P5Scalar).GetConstructor(ProtoRuntimeString), Runtime, Expression.Call( Generate(sub, op.Childs[0]), typeof(IP5Any).GetMethod("AsString"), Runtime)); } case Opcode.OpNumber.OP_LENGTH: { return Expression.New( typeof(P5Scalar).GetConstructor(ProtoRuntimeInt), Runtime, Expression.Call( Generate(sub, op.Childs[0]), typeof(IP5Any).GetMethod("StringLength"), Runtime)); } case Opcode.OpNumber.OP_JOIN: { return Expression.Call( typeof(Builtins).GetMethod("JoinList"), Runtime, Generate(sub, op.Childs[0])); } case Opcode.OpNumber.OP_ITERATOR: { return Expression.Call( Generate(sub, op.Childs[0]), typeof(P5Array).GetMethod("GetEnumerator", ProtoRuntime), Runtime); } case Opcode.OpNumber.OP_ITERATOR_NEXT: { Expression iter = Generate(sub, op.Childs[0]); Expression has_next = Expression.Call( iter, typeof(IEnumerator).GetMethod("MoveNext")); return Expression.Condition( has_next, Expression.Property(iter, "Current"), Expression.Constant(null, typeof(IP5Any))); } case Opcode.OpNumber.OP_SPLICE: { var args = new List<Expression>(); args.Add(Runtime); args.Add(Generate(sub, op.Childs[0])); if (op.Childs.Length > 1) args.Add(Generate(sub, op.Childs[1])); else args.Add(Expression.Constant(null, typeof(IP5Any))); if (op.Childs.Length > 2) args.Add(Generate(sub, op.Childs[2])); else args.Add(Expression.Constant(null, typeof(IP5Any))); if (op.Childs.Length > 3) { var list = new List<Expression>(); for (int i = 3; i < op.Childs.Length; ++i) list.Add(Generate(sub, op.Childs[i])); args.Add(Expression.NewArrayInit(typeof(IP5Any), list)); } if (op.Childs.Length <= 3) return Expression.Call( typeof(Builtins).GetMethod("ArraySplice"), args); else return Expression.Call( typeof(Builtins).GetMethod("ArrayReplace"), args); } case Opcode.OpNumber.OP_ARRAY_SLICE: { var ea = (ElementAccess)op; return Expression.Call( Generate(sub, op.Childs[0]), typeof(IP5Array).GetMethod("Slice"), Runtime, Generate(sub, op.Childs[1]), Expression.Constant(ea.Create != 0)); } case Opcode.OpNumber.OP_HASH_SLICE: { var ea = (ElementAccess)op; return Expression.Call( Generate(sub, op.Childs[0]), typeof(P5Hash).GetMethod("Slice"), Runtime, Generate(sub, op.Childs[1]), Expression.Constant(ea.Create != 0)); } case Opcode.OpNumber.OP_LIST_SLICE: { return Expression.Call( Generate(sub, op.Childs[0]), typeof(P5List).GetMethod("Slice", new Type[] { typeof(Runtime), typeof(P5Array) }), Runtime, Generate(sub, op.Childs[1])); } case Opcode.OpNumber.OP_KEYS: return Expression.Call( Generate(sub, op.Childs[0]), typeof(P5Hash).GetMethod("Keys"), Runtime); case Opcode.OpNumber.OP_VALUES: return Expression.Call( Generate(sub, op.Childs[0]), typeof(P5Hash).GetMethod("Values"), Runtime); case Opcode.OpNumber.OP_EACH: return Expression.Call( typeof(Builtins).GetMethod("HashEach"), Runtime, OpContext(op), Generate(sub, op.Childs[0])); case Opcode.OpNumber.OP_TEMPORARY: { Temporary tm = (Temporary)op; return GetTemporary(tm.Index, TypeForSlot(tm.Slot)); } case Opcode.OpNumber.OP_TEMPORARY_SET: { Temporary tm = (Temporary)op; Expression exp = Generate(sub, op.Childs[0]); return Expression.Assign(GetTemporary(tm.Index, TypeForSlot(tm.Slot)), exp); } case Opcode.OpNumber.OP_TEMPORARY_CLEAR: { Temporary tm = (Temporary)op; var type = TypeForSlot(tm.Slot); return Expression.Assign(GetTemporary(tm.Index, type), Expression.Constant(null, type)); } case Opcode.OpNumber.OP_LEXICAL: { Lexical lx = (Lexical)op; return lx.LexicalIndex == 0 && !IsMain ? Arguments : GetLexicalValue(lx.LexicalIndex, lx.Slot); } case Opcode.OpNumber.OP_LEXICAL_CLEAR: { Lexical lx = (Lexical)op; Expression lexvar = GetLexical(lx.LexicalIndex, lx.Slot); return Expression.Assign(lexvar, Expression.Constant(null, lexvar.Type)); } case Opcode.OpNumber.OP_LEXICAL_SET: { Lexical lx = (Lexical)op; Expression lexvar = GetLexical(lx.LexicalIndex, lx.Slot); return Expression.Assign( lexvar, Expression.Convert(Generate(sub, op.Childs[0]), lexvar.Type)); } case Opcode.OpNumber.OP_LEXICAL_PAD: { Lexical lx = (Lexical)op; return GetLexicalPadValue(lx.LexicalInfo); } case Opcode.OpNumber.OP_LEXICAL_PAD_CLEAR: { Lexical lx = (Lexical)op; Expression lexvar = GetLexicalPad(lx.LexicalInfo); return Expression.Assign(lexvar, Expression.Constant(null, lexvar.Type)); } case Opcode.OpNumber.OP_LEXICAL_PAD_SET: { Lexical lx = (Lexical)op; Expression lexvar = GetLexicalPad(lx.LexicalInfo); return Expression.Assign( lexvar, Expression.Convert(Generate(sub, op.Childs[0]), lexvar.Type)); } case Opcode.OpNumber.OP_LOCALIZE_LEXICAL_PAD: { LocalLexical lx = (LocalLexical)op; Expression lexvar = GetLexicalPad(lx.LexicalInfo); var saved = GetTemporary(lx.Index, typeof(IP5Any)); return Expression.Assign(saved, lexvar); } case Opcode.OpNumber.OP_RESTORE_LEXICAL_PAD: { var exps = new List<Expression>(); LocalLexical lx = (LocalLexical)op; Expression lexvar = GetLexicalPad(lx.LexicalInfo); var saved = GetTemporary(lx.Index, typeof(IP5Any)); exps.Add( Expression.IfThen( Expression.NotEqual( saved, Expression.Constant(null, saved.Type)), Expression.Assign(lexvar, saved))); exps.Add(Expression.Assign( saved, Expression.Constant(null, saved.Type))); return Expression.Block(typeof(void), exps); } case Opcode.OpNumber.OP_LOCALIZE_LEXICAL: { LocalLexical lx = (LocalLexical)op; Expression lexvar = GetLexical(lx.LexicalIndex, TypeForSlot(lx.Slot)); var saved = GetTemporary(lx.Index, TypeForSlot(lx.Slot)); return Expression.Assign(saved, lexvar); } case Opcode.OpNumber.OP_RESTORE_LEXICAL: { var exps = new List<Expression>(); LocalLexical lx = (LocalLexical)op; Expression lexvar = GetLexical(lx.LexicalIndex, TypeForSlot(lx.Slot)); var saved = GetTemporary(lx.Index, TypeForSlot(lx.Slot)); exps.Add( Expression.IfThen( Expression.NotEqual( saved, Expression.Constant(null, saved.Type)), Expression.Assign(lexvar, saved))); exps.Add(Expression.Assign( saved, Expression.Constant(null, saved.Type))); return Expression.Block(typeof(void), exps); } case Opcode.OpNumber.OP_VEC: { return Expression.New( typeof(P5Vec).GetConstructor(new[] { typeof(Runtime), typeof(IP5Any), typeof(IP5Any), typeof(IP5Any) }), Runtime, Generate(sub, op.Childs[0]), Generate(sub, op.Childs[1]), Generate(sub, op.Childs[2])); } case Opcode.OpNumber.OP_SUBSTR: { Expression value = Expression.Convert( Generate(sub, op.Childs[0]), typeof(P5Scalar)); Expression offset = Expression.Call( Generate(sub, op.Childs[1]), typeof(IP5Any).GetMethod("AsInteger"), Runtime); Expression length = null; if (op.Childs.Length >= 3) length = Expression.Call( Generate(sub, op.Childs[2]), typeof(IP5Any).GetMethod("AsInteger"), Runtime); if (op.Childs.Length == 4) return Expression.Call( value, typeof(P5Scalar).GetMethod("SpliceSubstring", new[] { typeof(Runtime), typeof(int), typeof(int), typeof(IP5Any) }), Runtime, offset, length, Generate(sub, op.Childs[3])); else if (op.Childs.Length == 3) return Expression.New( typeof(P5Substr).GetConstructor(new[] { typeof(Runtime), typeof(IP5Any), typeof(int), typeof(int) }), Runtime, value, offset, length); else if (op.Childs.Length == 2) return Expression.New( typeof(P5Substr).GetConstructor(new[] { typeof(Runtime), typeof(IP5Any), typeof(int) }), Runtime, value, offset); throw new System.Exception(); // can't happen } case Opcode.OpNumber.OP_BLESS: { return Expression.Call( typeof(Builtins).GetMethod("Bless"), Runtime, Expression.Convert(Generate(sub, op.Childs[0]), typeof(P5Scalar)), Generate(sub, op.Childs[1])); } case Opcode.OpNumber.OP_CALL_METHOD: { CallMethod cm = (CallMethod)op; return Expression.Call( Generate(sub, op.Childs[0]), typeof(P5Array).GetMethod("CallMethod"), Runtime, OpContext(op), Expression.Constant(cm.Method)); } case Opcode.OpNumber.OP_CALL_METHOD_INDIRECT: { return Expression.Call( Generate(sub, op.Childs[1]), typeof(P5Array).GetMethod("CallMethodIndirect"), Runtime, OpContext(op), Generate(sub, op.Childs[0])); } case Opcode.OpNumber.OP_FIND_METHOD: { CallMethod cm = (CallMethod)op; return Expression.Call( Generate(sub, op.Childs[0]), typeof(IP5Any).GetMethod("FindMethod"), Runtime, Expression.Constant(cm.Method)); } case Opcode.OpNumber.OP_CALL: { return Expression.Call( Generate(sub, op.Childs[1]), typeof(P5Code).GetMethod("Call"), Runtime, OpContext(op), Generate(sub, op.Childs[0])); } case Opcode.OpNumber.OP_REFTYPE: { return Expression.Call( ForceScalar(Generate(sub, op.Childs[0])), typeof(P5Scalar).GetMethod("ReferenceType"), Runtime); } case Opcode.OpNumber.OP_REFERENCE: { return Expression.New( typeof(P5Scalar).GetConstructor( new Type[] { typeof(Runtime), typeof(IP5Referrable) }), new Expression[] { Runtime, Generate(sub, op.Childs[0]) }); } case Opcode.OpNumber.OP_VIVIFY_SCALAR: { return Expression.Call( Generate(sub, op.Childs[0]), typeof(IP5Any).GetMethod("VivifyScalar"), Runtime); } case Opcode.OpNumber.OP_VIVIFY_ARRAY: { return Expression.Call( Generate(sub, op.Childs[0]), typeof(IP5Any).GetMethod("VivifyArray"), Runtime); } case Opcode.OpNumber.OP_VIVIFY_HASH: { return Expression.Call( Generate(sub, op.Childs[0]), typeof(IP5Any).GetMethod("VivifyHash"), Runtime); } case Opcode.OpNumber.OP_DEREFERENCE_SCALAR: { return Expression.Call( Generate(sub, op.Childs[0]), typeof(IP5Any).GetMethod("DereferenceScalar"), Runtime); } case Opcode.OpNumber.OP_DEREFERENCE_ARRAY: { return Expression.Call( Generate(sub, op.Childs[0]), typeof(IP5Any).GetMethod("DereferenceArray"), Runtime); } case Opcode.OpNumber.OP_DEREFERENCE_HASH: { return Expression.Call( Generate(sub, op.Childs[0]), typeof(IP5Any).GetMethod("DereferenceHash"), Runtime); } case Opcode.OpNumber.OP_DEREFERENCE_GLOB: { return Expression.Call( Generate(sub, op.Childs[0]), typeof(IP5Any).GetMethod("DereferenceGlob"), Runtime); } case Opcode.OpNumber.OP_DEREFERENCE_SUB: { return Expression.Call( Generate(sub, op.Childs[0]), typeof(IP5Any).GetMethod("DereferenceSubroutine"), Runtime); } case Opcode.OpNumber.OP_MAKE_CLOSURE: { return Expression.Call( Generate(sub, op.Childs[0]), typeof(P5Code).GetMethod("MakeClosure"), Runtime, Pad); } case Opcode.OpNumber.OP_MAKE_QR: { return Expression.New( typeof(P5Scalar).GetConstructor(new System.Type[] { typeof(Runtime), typeof(IP5Referrable) }), Runtime, Generate(sub, op.Childs[0])); } case Opcode.OpNumber.OP_LOCALIZE_GLOB_SLOT: { var exps = new List<Expression>(); var vars = new List<ParameterExpression>(); var lop = (LocalGlobSlot)op; var st = typeof(Runtime).GetField("SymbolTable"); var glob = Expression.Variable(typeof(P5Typeglob)); var saved = Expression.Variable(TypeForSlot(lop.Slot)); var temp = GetTemporary(lop.Index, typeof(IP5Any)); // FIXME do not walk twice the symbol table exps.Add( Expression.Assign( glob, Expression.Call( Expression.Field(Runtime, st), typeof(P5SymbolTable).GetMethod("GetGlob"), Runtime, Expression.Constant(lop.Name), Expression.Constant(true)))); exps.Add( Expression.Assign( temp, Expression.Call( Expression.Field(Runtime, st), typeof(P5SymbolTable).GetMethod(MethodForSlot(lop.Slot)), Runtime, Expression.Constant(lop.Name), Expression.Constant(true)))); exps.Add( Expression.Assign( saved, Expression.Convert( Expression.Call( temp, typeof(IP5Any).GetMethod("Localize"), Runtime), saved.Type))); exps.Add( Expression.Assign( Expression.Property( glob, PropertyForSlot(lop.Slot)), saved)); exps.Add(saved); vars.Add(glob); vars.Add(saved); return Expression.Block(typeof(IP5Any), vars, exps); } case Opcode.OpNumber.OP_RESTORE_GLOB_SLOT: { var exps = new List<Expression>(); var vars = new List<ParameterExpression>(); var lop = (LocalGlobSlot)op; var st = typeof(Runtime).GetField("SymbolTable"); var glob = Expression.Variable(typeof(P5Typeglob)); var saved = GetTemporary(lop.Index, typeof(IP5Any)); exps.Add( Expression.Assign( glob, Expression.Call( Expression.Field(Runtime, st), typeof(P5SymbolTable).GetMethod("GetGlob"), Runtime, Expression.Constant(lop.Name), Expression.Constant(true)))); exps.Add( Expression.Assign( Expression.Property( glob, PropertyForSlot(lop.Slot)), Expression.Convert( saved, TypeForSlot(lop.Slot)))); exps.Add( Expression.Assign( saved, Expression.Constant(null, saved.Type))); vars.Add(glob); return Expression.IfThen( Expression.NotEqual( saved, Expression.Constant(null, typeof(IP5Any))), Expression.Block(typeof(IP5Any), vars, exps)); } case Opcode.OpNumber.OP_LOCALIZE_ARRAY_ELEMENT: { var le = (LocalElement)op; return Expression.Call( typeof(Builtins).GetMethod("LocalizeArrayElement"), Runtime, Generate(sub, le.Childs[0]), Generate(sub, le.Childs[1]), GetTemporary(le.Index, typeof(SavedValue))); } case Opcode.OpNumber.OP_RESTORE_ARRAY_ELEMENT: { var le = (LocalElement)op; return Expression.Call( typeof(Builtins).GetMethod("RestoreArrayElement"), Runtime, GetTemporary(le.Index, typeof(SavedValue))); } case Opcode.OpNumber.OP_LOCALIZE_HASH_ELEMENT: { var le = (LocalElement)op; return Expression.Call( typeof(Builtins).GetMethod("LocalizeHashElement"), Runtime, Generate(sub, le.Childs[0]), Generate(sub, le.Childs[1]), GetTemporary(le.Index, typeof(SavedValue))); } case Opcode.OpNumber.OP_RESTORE_HASH_ELEMENT: { var le = (LocalElement)op; return Expression.Call( typeof(Builtins).GetMethod("RestoreHashElement"), Runtime, GetTemporary(le.Index, typeof(SavedValue))); } case Opcode.OpNumber.OP_LEXICAL_STATE_SET: { var ls = (LexState)op; var state = sub.LexicalStates[ls.Index]; // force package creation if (state.Package != null) DefinePackage(state.Package); return Expression.Block( typeof(void), Expression.Assign( Expression.Field(Runtime, "Package"), Expression.Constant(state.Package)), Expression.Assign( Expression.Field(Runtime, "Hints"), Expression.Constant(state.Hints))); } case Opcode.OpNumber.OP_LEXICAL_STATE_SAVE: { var ls = (LexState)op; var slot = GetSavedLexState(ls.Index); return Expression.Block( typeof(void), Expression.Assign( Expression.Field(slot, "Package"), Expression.Field(Runtime, "Package")), Expression.Assign( Expression.Field(slot, "Hints"), Expression.Field(Runtime, "Hints"))); } case Opcode.OpNumber.OP_LEXICAL_STATE_RESTORE: { var ls = (LexState)op; var slot = GetSavedLexState(ls.Index); return Expression.Block( typeof(void), Expression.Assign( Expression.Field(Runtime, "Package"), Expression.Field(slot, "Package")), Expression.Assign( Expression.Field(Runtime, "Hints"), Expression.Field(slot, "Hints"))); } case Opcode.OpNumber.OP_CALLER: { return op.Childs.Length == 0 ? Expression.Call( Runtime, typeof(Runtime).GetMethod("CallerNoArg"), OpContext(op)) : Expression.Call( Runtime, typeof(Runtime).GetMethod("CallerWithArg"), Generate(sub, op.Childs[0]), OpContext(op)); } case Opcode.OpNumber.OP_CONSTANT_REGEX: { var cs = (ConstantSub)op; return ConstantRegex(cs.Value); } case Opcode.OpNumber.OP_EVAL_REGEX: { RegexEval re = (RegexEval)op; return Expression.Call( typeof(Builtins).GetMethod("CompileRegex"), Runtime, Expression.Call( Generate(sub, re.Childs[0]), typeof(IP5Any).GetMethod("AsScalar"), Runtime), Expression.Constant(re.Flags)); } case Opcode.OpNumber.OP_POS: { return Expression.New( typeof(P5Pos).GetConstructor(ProtoRuntimeAny), Runtime, Generate(sub, op.Childs[0])); } case Opcode.OpNumber.OP_RX_STATE_RESTORE: { RegexState rs = (RegexState)op; return Expression.Assign( Expression.Field(Runtime, "LastMatch"), GetSavedRxState(rs.Index)); } case Opcode.OpNumber.OP_MATCH: { RegexMatch rm = (RegexMatch)op; bool global = (rm.Flags & Opcode.RX_GLOBAL) != 0; var meth = typeof(IP5Regex).GetMethod(global ? "MatchGlobal" : "Match"); return Expression.Call( Generate(sub, op.Childs[1]), meth, Runtime, Generate(sub, op.Childs[0]), Expression.Constant(rm.Flags & Opcode.RX_KEEP), OpContext(rm), GetSavedRxState(rm.Index)); } case Opcode.OpNumber.OP_REPLACE: { RegexReplace rm = (RegexReplace)op; bool global = (rm.Flags & Opcode.RX_GLOBAL) != 0; if (global) return GenerateGlobalSubstitution(sub, rm); else return GenerateSubstitution(sub, rm); } case Opcode.OpNumber.OP_RX_SPLIT_SKIPSPACES: return Expression.Call( typeof(Builtins).GetMethod("SplitSpaces"), Runtime, Generate(sub, op.Childs[0])); case Opcode.OpNumber.OP_TRANSLITERATE: { RegexTransliterate rt = (RegexTransliterate)op; return Expression.New( typeof(P5Scalar).GetConstructor(ProtoRuntimeInt), Runtime, Expression.Call( typeof(Builtins).GetMethod("Transliterate"), Runtime, Generate(sub, rt.Childs[0]), Expression.Constant(rt.Match), Expression.Constant(rt.Replacement), Expression.Constant(rt.Flags))); } case Opcode.OpNumber.OP_UNLINK: return Expression.Call( typeof(Builtins).GetMethod("Unlink"), Runtime, Generate(sub, op.Childs[0])); case Opcode.OpNumber.OP_OPEN: return Expression.Call( typeof(Builtins).GetMethod("Open"), Runtime, Generate(sub, op.Childs[0])); case Opcode.OpNumber.OP_CLOSE: return Expression.Call( typeof(Builtins).GetMethod("Close"), Runtime, Generate(sub, op.Childs[0])); case Opcode.OpNumber.OP_FT_ISFILE: return Expression.Call( typeof(Builtins).GetMethod("IsFile"), Runtime, Generate(sub, op.Childs[0])); default: throw new System.Exception(string.Format("Unhandled opcode {0:S} in generation", op.Number.ToString())); } }
private Type TypeForSlot(Opcode.Sigil slot) { return slot == Opcode.Sigil.SCALAR ? typeof(P5Scalar) : slot == Opcode.Sigil.INDEXABLE? typeof(IP5Array) : slot == Opcode.Sigil.HASH ? typeof(P5Hash) : slot == Opcode.Sigil.ITERATOR ? typeof(IEnumerator<IP5Any>) : slot == Opcode.Sigil.GLOB ? typeof(P5Typeglob) : slot == Opcode.Sigil.SUB ? typeof(P5Code) : slot == Opcode.Sigil.HANDLE ? typeof(P5Handle) : slot == Opcode.Sigil.ARRAY ? typeof(P5Array) : typeof(void); }
protected abstract Expression Defined(Subroutine sub, Opcode op);