mirror of
https://github.com/SSCLI/sscli_20021101
synced 2026-06-08 12:28:57 +00:00
9fa3874800
Moved the original file to the archive subfolder.
239 lines
8.6 KiB
C#
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;
|
|
}
|
|
|
|
|
|
}
|
|
}
|