protected static bool Apply( ref Tflag flags, Opcode code ) { if( code.Kind() == Opkind.Access ) { if( code == Opcode.Internal ) { flags |= Tflag.Internal; } else { flags = ((Tflag)(unchecked((byte)code) & 3)) | (flags & (~((Tflag)3))); } return true; } if( code.Kind() == Opkind.Scope ) { if( ((code == Opcode.Readonly) && (flags.Scope() == Tflag.Static)) || ((code == Opcode.Static) && (flags.Scope() == Tflag.Readonly)) ) { flags = Tflag.Rostatic | (flags & (~Tflag.Scope)); } else { flags = ((Tflag)((unchecked((byte)code) & 7) << 4)) | (flags & (~Tflag.Scope)); } return true; } if( code == Opcode.Partial ) { flags |= Tflag.Partial; return true; } if( code == Opcode.Unsafe ) { flags |= Tflag.Unsafe; return true; } return false; }//Apply
/// <summary> /// prepare top operator (prepare postfix record or expression tree node) /// </summary> void Parser.IGenerator.Prepare( Opcode op ) { Debug.Assert( (op.Kind() <= Opkind.Prepost) && (op.Kind() >= Opkind.Special) ); if( op.Binary() ) { goto binary; } if( op.Ternary() ) { goto ternary; } if( op.Multi() ) { goto multi; } Debug.Assert( op.Unary() ); var start = PopInt(); Vneed( 1 ); Vpush( unchecked((byte)op) ); Vpush( start ); return; binary: var rstart = TopInt(); var lstart = TopInt( rstart ); Vneed( 5 ); Vpush( op.Code() ); Vpush( lstart ); return; ternary: var fstart = TopInt(); var tstart = TopInt( fstart ); var cstart = TopInt( tstart ); Vneed( 5 ); Vpush( op.Code() ); Vpush( cstart ); return; multi: Debug.Assert( (((op == Opcode.Mcall) || (op == Opcode.Mindex)) || (op == Opcode.Array)) || (op == Opcode.Generic) ); var mstart = TopInt(); var n = 1; if( (op == Opcode.Mcall) || (op == Opcode.Mindex) ) { n++; mstart = TopInt( mstart ); } while( (Parser.OpsAt > 0) && (Parser.Top() == Opcode.Comma) ){ Parser.Pop(); n++; mstart = TopInt( mstart ); } if( n > 127 ) { throw new ParseError( Parser, "Too many arguments" ); } if( (n == 3) && (op == Opcode.Mcall) ) { Vneed( 5 ); Vpush( unchecked((byte)Opcode.Call2) ); Vpush( mstart ); return; } Vneed( 6 ); Vpush( unchecked((byte)n) ); Vpush( op.Code() ); Vpush( mstart ); return; }//Parser.IGenerator.Prepare
}//Literal protected override void Special( Opcode op, byte[] code, ref int at ) { var create = false; next: switch( op ) { case Opcode.Create: create = true; op = ((Opcode)code[at]).Extend(); if( (op.Kind() == Opkind.Special) && (unchecked((byte)op) < unchecked((byte)Opcode.Generic)) ) { at++; goto next; } goto case Opcode.Ecall; case Opcode.Ecall: if( create ) { Typeref( code, ref at ); } else { Expression( code, ref at ); } Obj self = null; if( Value.Type == Vtype.Ident ) { self = Value.Ptr as Obj; Value = ((IProps)Value.Ptr).Get( Value.Str ); } var fn = Box( Value ); Value = create ? new Value( fn.Create( 0 ) ) : fn.Call( self, 0 ); return; case Opcode.Call: if( create ) { Typeref( code, ref at ); } else { Expression( code, ref at ); } self = null; if( Value.Type == Vtype.Ident ) { self = Value.Ptr as Obj; Value = ((IProps)Value.Ptr).Get( Value.Str ); } fn = Box( Value ); Expression( code, ref at ); Args.Add( Result ); Value = create ? new Value( fn.Create( 1 ) ) : fn.Call( self, 1 ); Args.Remove( 1 ); return; case Opcode.Call2: if( create ) { Typeref( code, ref at ); } else { Expression( code, ref at ); } self = null; if( Value.Type == Vtype.Ident ) { self = Value.Ptr as Obj; Value = ((IProps)Value.Ptr).Get( Value.Str ); } fn = Box( Value ); Expression( code, ref at ); Args.Add( Result ); Expression( code, ref at ); Args.Add( Result ); Value = create ? new Value( fn.Create( 2 ) ) : fn.Call( self, 2 ); Args.Remove( 2 ); return; case Opcode.Mcall: int n = code[at++]; if( create ) { Typeref( code, ref at ); } else { Expression( code, ref at ); } self = null; if( Value.Type == Vtype.Ident ) { self = Value.Ptr as Obj; Value = ((IProps)Value.Ptr).Get( Value.Str ); } fn = Box( Value ); var argc = n - 1; while( (--n) > 0 ){ Expression( code, ref at ); Args.Add( Result ); } Value = create ? new Value( fn.Create( argc ) ) : fn.Call( self, argc ); Args.Remove( argc ); return; case Opcode.Index: case Opcode.Mindex: n = op == Opcode.Index ? 2 : code[at++]; Expression( code, ref at ); self = null; if( Value.Type == Vtype.Ident ) { self = Value.Ptr as Obj; Value = ((IProps)Value.Ptr).Get( Value.Str ); } fn = Box( Value ); argc = n - 1; while( (--n) > 0 ){ Expression( code, ref at ); Args.Add( Result ); } Value = fn.Index( self, argc ); Args.Remove( argc ); return; case Opcode.Var: var ident = Cident( code, ref at ); Typeref( code, ref at ); if( Value.Type == Vtype.Undef ) { Expression( code, ref at ); Ctx.Vars.Set( ident, Value ); return; } fn = Box( Value ); Expression( code, ref at ); Args.Add( Result ); Value = fn.Call( null, 1 ); Args.Remove( 1 ); Ctx.Vars.Set( ident, Value ); return; case Opcode.Dot: Expression( code, ref at ); fn = Box( Value ); ident = Cident( code, ref at ); Value = new Value( fn, ident ); return; case Opcode.Ternary: Expression( code, ref at ); if( Result.Bool ) { at += 4; Expression( code, ref at ); var fsz = Cint( code, ref at ); at += fsz; } else { var tsz = Cint( code, ref at ); at += tsz; at += 4; Expression( code, ref at ); } return; } throw new NotImplementedException(); }//Special
protected override void Statement( Opcode op, byte[] code, ref int at ) { Debug.Assert( (op.Kind() == Opkind.Statement) || (op.Kind() == Opkind.Statement2) ); switch( op ) { default: throw new NotImplementedException(); case Opcode.Block: if( (Opts & Opt.BlockScope) != 0 ) { Ctx.Push( this ); } Block( code, ref at ); if( (Opts & Opt.BlockScope) != 0 ) { Ctx.Pop(); } return; case Opcode.Return: case Opcode.Raise: Expression( code, ref at ); goto case Opcode.Break; case Opcode.Break: case Opcode.Continue: Exit = op; return; case Opcode.For: if( (Opts & Opt.BlockScope) != 0 ) { Ctx.Push( this ); } Expression( code, ref at ); var test = at; var notest = code[at] == 0; if( notest ) { ++at; } else { Expression( code, ref at ); } var size = Cint( code, ref at ); var last = at; var stts = at + size; var cend = (stts + 4) + Bits.Int( code, stts ); if( (Value.Type != Vtype.Undef) && (!Value.Bool) ) { at = cend; if( (Opts & Opt.BlockScope) != 0 ) { Ctx.Pop(); } return; } for( ; ; ) { at = stts; Block( code, ref at ); if( (Exit != 0) && (Exit != Opcode.Continue) ) { break; } at = last; Expression( code, ref at ); if( !notest ) { at = test; Expression( code, ref at ); if( !Value.Bool ) { break; } } } at = cend; if( (Opts & Opt.BlockScope) != 0 ) { Ctx.Pop(); } if( (Exit == Opcode.Break) || (Exit == Opcode.Continue) ) { Exit = 0; } return; case Opcode.While: case Opcode.Until: if( (Opts & Opt.BlockScope) != 0 ) { Ctx.Push( this ); } test = at; do { at = test; Expression( code, ref at ); if( Value.Bool == (op == Opcode.Until) ) { break; } Block( code, ref at ); } while( (Exit == 0) || (Exit == Opcode.Continue) ); if( (Opts & Opt.BlockScope) != 0 ) { Ctx.Pop(); } if( (Exit == Opcode.Break) || (Exit == Opcode.Continue) ) { Exit = 0; } return; case Opcode.Do: case Opcode.Dountil: if( (Opts & Opt.BlockScope) != 0 ) { Ctx.Push( this ); } do { Block( code, ref at ); if( (Exit != 0) && (Exit != Opcode.Continue) ) { break; } Expression( code, ref at ); } while( Value.Bool != (op == Opcode.Dountil) ); if( (Opts & Opt.BlockScope) != 0 ) { Ctx.Pop(); } if( (Exit == Opcode.Break) || (Exit == Opcode.Continue) ) { Exit = 0; } return; case Opcode.If: if( (Opts & Opt.BlockScope) != 0 ) { Ctx.Push( this ); } Expression( code, ref at ); if( Value.Bool ) { Block( code, ref at ); if( (at < code.Length) && (code[at] == unchecked((byte)Opcode.Else)) ) { at++; size = Cint( code, ref at ); at += size; } } else { size = Cint( code, ref at ); at += size; if( (at < code.Length) && (code[at] == unchecked((byte)Opcode.Else)) ) { at++; Block( code, ref at ); } } if( (Opts & Opt.BlockScope) != 0 ) { Ctx.Pop(); } return; } }//Statement
}//Unary protected override void Special( Opcode op, byte[] code, ref int at ) { var paren = Parens; var create = false; next: switch( op ) { case Opcode.Create: create = true; Write( "new " ); op = ((Opcode)code[at]).Extend(); if( (op.Kind() == Opkind.Special) && (unchecked((byte)op) < unchecked((byte)Opcode.Generic)) ) { at++; goto next; } goto case Opcode.Ecall; case Opcode.Ecall: if( create ) { if( code[at] == unchecked((byte)Opcode.Array) ) { Typeref( code, ref at ); return; } Typeref( code, ref at ); } else { Expression( code, ref at ); } Write( "()" ); return; case Opcode.Call: if( create ) { Typeref( code, ref at ); } else { Expression( code, ref at ); } Write( paren ? '(' : ' ' ); Expression( code, ref at ); if( paren ) { Write( ')' ); } return; case Opcode.Call2: if( create ) { Typeref( code, ref at ); } else { Expression( code, ref at ); } Write( paren ? '(' : ' ' ); Expression( code, ref at ); Write( ", " ); Expression( code, ref at ); if( paren ) { Write( ')' ); } return; case Opcode.Mcall: var mcn = ((int)(code[at++] - 1)); if( mcn < 2 ) { throw new InvalidOperationException(); } if( create ) { Typeref( code, ref at ); } else { Expression( code, ref at ); } Write( paren ? '(' : ' ' ); Expression( code, ref at ); while( (--mcn) > 0 ){ Write( ", " ); Expression( code, ref at ); } if( paren ) { Write( ')' ); } return; case Opcode.Index: Expression( code, ref at ); Write( '[' ); Current = 0; Expression( code, ref at ); Current = op; Write( ']' ); return; case Opcode.Mindex: mcn = ((int)(code[at++] - 1)); if( mcn < 2 ) { throw new InvalidOperationException(); } Expression( code, ref at ); Write( '[' ); Expression( code, ref at ); while( (--mcn) > 0 ){ Write( ", " ); Expression( code, ref at ); } Write( ']' ); return; case Opcode.Var: var n = code[at++]; var s = Encoding.UTF8.GetString( code, at, n ); at += n; Write( "var " ); Write( s ); if( code[at] == 0 ) { at++; } else { Write( ' ' ); Typeref( code, ref at ); } if( code[at] == 0 ) { at++; } else { Write( " = " ); Expression( code, ref at ); } return; case Opcode.Dot: Expression( code, ref at ); Write( '.' ); n = code[at++]; Write( Encoding.UTF8.GetString( code, at, n ) ); at += n; return; case Opcode.Ternary: if( paren ) { Write( '(' ); } Expression( code, ref at ); Write( " ? " ); at += 4; Current = 0; Expression( code, ref at ); Write( " : " ); at += 4; Expression( code, ref at ); Current = op; if( paren ) { Write( ')' ); } return; } throw new NotImplementedException(); }//Special
}//Nibble /// <summary> /// rewrite literal from parsed value buffer/stack to code buffer /// </summary> protected override void Literal( Opcode op, int top, int start ) { if( op == Opcode.Ident ) { Copy( op, true, top, start ); return; } if( (op < Opcode.Ident) || (op == Opcode.Exception) ) { Write( unchecked((byte)op) ); return; } var len = top - start; if( (op.Kind() <= Opkind.Number) && (unchecked((byte)op) >= unchecked((byte)Opcode.Char)) ) { Debug.Assert( op <= Opcode.Double ); Debug.Assert( len == op.Numsz() ); Need( len + 1 ); Code[CodeAt++] = unchecked((byte)op); Array.Copy( Vals, start, Code, CodeAt, len ); CodeAt += len; return; } Debug.Assert( op == Opcode.String ); if( len < (1 << 7) ) { Copy( op, true, top, start ); return; } if( len < (1 << 14) ) { Need( 3 + len ); Code[CodeAt++] = unchecked((byte)op); Code[CodeAt++] = unchecked((byte)(0x80 | len)); Code[CodeAt++] = unchecked((byte)(len >> 7)); Array.Copy( Vals, start, Code, CodeAt, len ); CodeAt += len; return; } if( len < (1 << 21) ) { Need( 4 + len ); Code[CodeAt++] = unchecked((byte)op); Code[CodeAt++] = unchecked((byte)(0x80 | len)); Code[CodeAt++] = unchecked((byte)(0x80 | (len >> 7))); Code[CodeAt++] = unchecked((byte)(len >> 14)); Array.Copy( Vals, start, Code, CodeAt, len ); CodeAt += len; return; } if( len < (1 << 28) ) { Need( 5 + len ); Code[CodeAt++] = unchecked((byte)op); Code[CodeAt++] = unchecked((byte)(0x80 | len)); Code[CodeAt++] = unchecked((byte)(0x80 | (len >> 7))); Code[CodeAt++] = unchecked((byte)(0x80 | (len >> 14))); Code[CodeAt++] = unchecked((byte)(len >> 21)); Array.Copy( Vals, start, Code, CodeAt, len ); CodeAt += len; return; } throw new InvalidOperationException(); }//Literal
}//Literal protected override void Special( Opcode op, byte[] code, ref int at ) { var create = false; next: switch( op ) { default: base.Special( op, code, ref at ); return; case Opcode.Create: create = true; Write( "new " ); op = ((Opcode)code[at]).Extend(); if( (op.Kind() == Opkind.Special) && (unchecked((byte)op) < unchecked((byte)Opcode.Generic)) ) { at++; goto next; } goto case Opcode.Ecall; case Opcode.Ecall: if( create ) { if( code[at] == unchecked((byte)Opcode.Array) ) { Typeref( code, ref at ); return; } Typeref( code, ref at ); } else { Expression( code, ref at ); } Write( "()" ); return; case Opcode.Call: if( create ) { Typeref( code, ref at ); } else { Expression( code, ref at ); } Write( '(' ); Expression( code, ref at ); Write( ')' ); return; case Opcode.Call2: if( create ) { Typeref( code, ref at ); } else { Expression( code, ref at ); } Write( '(' ); Expression( code, ref at ); Write( ", " ); Expression( code, ref at ); Write( ')' ); return; case Opcode.Mcall: var mcn = ((int)(code[at++] - 1)); if( mcn < 2 ) { throw new InvalidOperationException(); } if( create ) { Typeref( code, ref at ); } else { Expression( code, ref at ); } Write( '(' ); Expression( code, ref at ); while( (--mcn) > 0 ){ Write( ", " ); Expression( code, ref at ); } Write( ')' ); return; case Opcode.Dot: Debug.Assert( Name.Length == 0 ); Expression( code, ref at ); var s = Cident( code, ref at ); if( Name.Length == 0 ) { Write( '.' ); Write( Unalias( s, true ) ); return; } Name.Append( '.' ); Name.Append( s ); if( Inside != Opcode.Dot ) { Write( Unalias() ); } return; case Opcode.Var: s = Cident( code, ref at ); if( s[0] == '$' ) { s = s.Substring( 1 ); } else if( Aliasing != Alias.None ) { if( Aliasing == Alias.FirstUpper ) { s = System.Char.ToUpper( s[0] ) + s.Substring( 1 ); } else { AddLocal( s ); } } if( code[at] == 0 ) { at++; Write( "var " ); Write( s ); } else { Typeref( code, ref at ); Write( ' ' ); Write( s ); } if( code[at] == 0 ) { at++; } else { Write( " = " ); Expression( code, ref at ); } return; } }//Special