Files
yallie 9fa3874800 Added the contents of the archive.
Moved the original file to the archive subfolder.
2017-11-20 16:11:42 +03:00

239 lines
8.6 KiB
C#

// ==++==
//
//
// Copyright (c) 2002 Microsoft Corporation. All rights reserved.
//
// The use and distribution terms for this software are contained in the file
// named license.txt, which can be found in the root of this distribution.
// By using this software in any fashion, you are agreeing to be bound by the
// terms of this license.
//
// You must not remove this notice, or any other, from this software.
//
//
// ==--==
namespace Microsoft.JScript
{
using Microsoft.JScript.Vsa;
using System;
using System.Reflection;
using System.Reflection.Emit;
public abstract class AST{
internal Context context;
internal AST(Context context){
this.context = context;
}
internal virtual void CheckIfOKToUseInSuperConstructorCall(){
}
internal CompilerGlobals compilerGlobals{
get{
return this.context.document.compilerGlobals;
}
}
internal virtual bool Delete(){
return true; //This is according to spec, but not backwards compatible with JS5. The latter throws an exception.
}
//Run up the scope chain until a FunctionScope or GlobalScope/StackFrame is encountered.
//For a FunctionScope, defer to the owner.
//For a ClassScope, get the engine from a CRS static, or make a new engine
//For the GlobalScope, load the corresponding field of the this object.
internal void EmitILToLoadEngine(ILGenerator il){
ScriptObject scope = this.Engine.ScriptObjectStackTop();
while (scope != null && (scope is WithObject || scope is BlockScope))
scope = scope.GetParent();
if (scope is FunctionScope)
((FunctionScope)scope).owner.TranslateToILToLoadEngine(il);
else if (scope is ClassScope) //Inside a static initializer routine
if (this.Engine.doCRS)
il.Emit(OpCodes.Ldsfld, CompilerGlobals.contextEngineField);
else{
if (this.context.document.engine.PEFileKind == PEFileKinds.Dll){
il.Emit(OpCodes.Ldtoken, ((ClassScope)scope).GetTypeBuilder());
il.Emit(OpCodes.Call, CompilerGlobals.createVsaEngineWithType);
}else
il.Emit(OpCodes.Call, CompilerGlobals.createVsaEngine);
}
else{
//NOTE: a StackFrame is ecountered at compile time only when there is an eval.
//Eval does not translate to IL so we should only get here if the scope is a GlobalScope
Debug.Assert(scope is GlobalScope);
il.Emit(OpCodes.Ldarg_0);
il.Emit(OpCodes.Ldfld, CompilerGlobals.engineField);
}
}
internal VsaEngine Engine{
get{
return this.context.document.engine;
}
}
internal abstract Object Evaluate();
internal virtual LateBinding EvaluateAsLateBinding(){
return new LateBinding(null, this.Evaluate(), VsaEngine.executeForJSEE);
}
internal virtual WrappedNamespace EvaluateAsWrappedNamespace(bool giveErrorIfNameInUse){
throw new JScriptException(JSError.InternalError, this.context);
}
internal Globals Globals{
get{
return this.context.document.engine.Globals;
}
}
internal virtual bool HasReturn(){
return false;
}
internal virtual IReflect InferType(JSField inference_target){
return Typeob.Object;
}
internal virtual void InvalidateInferredTypes(){
//No need to do anything at this level.
}
internal virtual bool OkToUseAsType(){
return false;
}
internal abstract AST PartiallyEvaluate();
internal virtual AST PartiallyEvaluateAsCallable(){
return new CallableExpression(this.PartiallyEvaluate());
}
internal virtual AST PartiallyEvaluateAsReference(){
return this.PartiallyEvaluate();
}
internal virtual void ResolveCall(ASTList args, IReflect[] argIRs, bool constructor, bool brackets){
throw new JScriptException(JSError.InternalError, this.context);
}
internal virtual Object ResolveCustomAttribute(ASTList args, IReflect[] argIRs, AST target){
throw new JScriptException(JSError.InternalError, this.context);
}
internal virtual void SetPartialValue(AST partial_value){
this.context.HandleError(JSError.IllegalAssignment);
}
internal virtual void SetValue(Object value){
this.context.HandleError(JSError.IllegalAssignment);
}
internal virtual void TranslateToConditionalBranch(ILGenerator il, bool branchIfTrue, Label label, bool shortForm){
//This method is overridden in all interesting cases.
IReflect ir = this.InferType(null);
if (ir != Typeob.Object && ir is Type){
String op = branchIfTrue ? "op_True" : "op_False";
MethodInfo meth = ir.GetMethod(op, BindingFlags.ExactBinding|BindingFlags.Public|BindingFlags.Static, null, new Type[]{(Type)ir}, null);
if (meth != null){
this.TranslateToIL(il, (Type)ir);
il.Emit(OpCodes.Call, meth);
il.Emit(OpCodes.Brtrue, label);
return;
}
}
Type t = Convert.ToType(ir);
this.TranslateToIL(il, t);
Convert.Emit(this, il, t, Typeob.Boolean, true);
if (branchIfTrue)
il.Emit(shortForm ? OpCodes.Brtrue_S : OpCodes.Brtrue, label);
else
il.Emit(shortForm ? OpCodes.Brfalse_S : OpCodes.Brfalse, label);
}
internal abstract void TranslateToIL(ILGenerator il, Type rtype);
internal virtual void TranslateToILCall(ILGenerator il, Type rtype, ASTList args, bool construct, bool brackets){
throw new JScriptException(JSError.InternalError, this.context);
}
internal virtual void TranslateToILDelete(ILGenerator il, Type rtype){
if (rtype != Typeob.Void){
il.Emit(OpCodes.Ldc_I4_1); //This is according to spec, but not backwards compatible with JS5. The latter throws an exception.
Convert.Emit(this, il, Typeob.Boolean, rtype);
}
}
internal virtual void TranslateToILInitializer(ILGenerator il){
throw new JScriptException(JSError.InternalError, this.context);
}
internal virtual void TranslateToILPreSet(ILGenerator il){
throw new JScriptException(JSError.InternalError, this.context);
}
internal virtual void TranslateToILPreSet(ILGenerator il, ASTList args){
this.TranslateToIL(il, Typeob.Object);
args.TranslateToIL(il, typeof(Object[]));
}
internal virtual void TranslateToILPreSetPlusGet(ILGenerator il){
throw new JScriptException(JSError.InternalError, this.context);
}
internal virtual void TranslateToILPreSetPlusGet(ILGenerator il, ASTList args, bool inBrackets){
il.Emit(OpCodes.Ldnull); //Put a dummy this obj on the stack for CallValue's sake
this.TranslateToIL(il, Typeob.Object);
il.Emit(OpCodes.Dup);
LocalBuilder savedOb = il.DeclareLocal(Typeob.Object);
il.Emit(OpCodes.Stloc, savedOb);
args.TranslateToIL(il, typeof(Object[]));
il.Emit(OpCodes.Dup);
LocalBuilder savedArgs = il.DeclareLocal(typeof(Object[]));
il.Emit(OpCodes.Stloc, savedArgs);
il.Emit(OpCodes.Ldc_I4_0);
if (inBrackets)
il.Emit(OpCodes.Ldc_I4_1);
else
il.Emit(OpCodes.Ldc_I4_0);
this.EmitILToLoadEngine(il);
il.Emit(OpCodes.Call, CompilerGlobals.callValueMethod);
LocalBuilder savedResult = il.DeclareLocal(Typeob.Object);
il.Emit(OpCodes.Stloc, savedResult);
il.Emit(OpCodes.Ldloc, savedOb);
il.Emit(OpCodes.Ldloc, savedArgs);
il.Emit(OpCodes.Ldloc, savedResult);
}
internal void TranslateToILSet(ILGenerator il){
this.TranslateToILSet(il, null);
}
internal virtual void TranslateToILSet(ILGenerator il, AST rhvalue){
if (rhvalue != null)
rhvalue.TranslateToIL(il, Typeob.Object);
il.Emit(OpCodes.Call, CompilerGlobals.setIndexedPropertyValueStaticMethod);
}
internal virtual Object TranslateToILReference(ILGenerator il, Type rtype){
this.TranslateToIL(il, rtype);
LocalBuilder tok = il.DeclareLocal(rtype);
il.Emit(OpCodes.Stloc, tok);
il.Emit(OpCodes.Ldloca, tok);
return tok;
}
internal virtual Context GetFirstExecutableContext(){
return this.context;
}
}
}