public ClassMember(string name, ITypeDef typeDef, IExpr initializer, bool isGetonly) { this.name = name; this.typeDef = typeDef; this.initializer = initializer; this.isGetonly = isGetonly; }
// Returns true if it succeeds, false if there was a name conflict. public bool AddMember(string name, ITypeDef typeDef, IExpr initializer = null, bool isStatic = false, bool isFunctionVariable = false, bool isGetonly = false) { // Fail if a member with that name already exists. if (DoesFieldExist(name, SEARCH.EITHER)) { return(false); } var member = new ClassMember(name, typeDef, initializer, isGetonly); // This logic is weird but works because the language currently // doesn't allow static member functions. if (isStatic) { member.index = _statics.Add(member.name, member); staticVars.Add(new Variable(member.name, typeDef, null)); } else if (!isFunctionVariable && typeDef is TypeDef_Function) { member.index = _memberFuncs.Add(member.name, member); } else { member.index = _fields.Add(member.name, member); } return(true); }
/// <summary> /// Builds a new type from the provided list of properties. The new type implements IObjectAccessor interface /// </summary> /// <param name="typeDef">Type definition with list of property names and corresponding types.</param> /// <returns>Newly created type</returns> public static Type MakeType(ITypeDef typeDef) { if (typeDef == null) { throw new ArgumentNullException("typeDef"); } string typeName = typeDef.Name; if (string.IsNullOrEmpty(typeName)) { typeName = MakeUniqueName(); } s_lock.EnterWriteLock(); try { TypeBuilder tb = s_mb.DefineType(typeName, TypeAttributes.Public); tb.SetParent(typeof(ObjectAccessorBase <>).MakeGenericType(tb)); int order = 0; foreach (var fb in typeDef.PropertyDefList.Select(entry => tb.DefineField(entry.Key, entry.Value.ResolveType(), FieldAttributes.Public))) { AddOrderAttribute(fb, order++); } return(tb.CreateType()); } finally { s_lock.ExitWriteLock(); } }
// set uses this to 1) check to see if symbol already exists, and 2) caches the variable for use during evaluate // set can also be used to set global variables. // for uses this to 1) check to make sure symbol doesn't already exist, 2) push var on the stack for type checking public VarStackRef CreateTemp(string symbol, ITypeDef type, bool global = false, bool doesntCollideWithGlobal = false, bool unique = false) { if (null != GetTypeByName(symbol)) { return(new VarStackRef(VarStackRef.ErrorType.AlreadyExists)); } if (Pb.reservedWords.Contains(symbol)) { return(new VarStackRef(VarStackRef.ErrorType.ReservedSymbol)); } // Unsure about this null VarStackRef existingRef = stack.GetVarIndexByName(null, symbol, true); if (existingRef.isValid) { if (!(doesntCollideWithGlobal && existingRef.isGlobal)) { return(new VarStackRef(VarStackRef.ErrorType.AlreadyExists)); } } if (unique) { Variable var = new Variable(symbol, type, null); return(stack.AddExistingVariable(symbol, global, var)); } else { return(stack.AddVariable(symbol, global, type, null)); } }
/* Todo, perhaps: Add function which allows C# to add static functions later. Could help C#-Pebble communication. * public Variable AddStaticLiteralAfterFinalization(ExecContext context, string name, ITypeDef typeDef, object value) { * Variable variable = new Variable(name, typeDef); * staticVars.Add(variable); * variable.value = value; * return variable; * } */ // Use to add an override of a member function. // Caller is responsible for checking that... // 1) we have a parent // 2) it has a function with this name. public void AddFunctionOverride(string name, ITypeDef typeDef, IExpr initializer = null) { var member = new ClassMember(name, typeDef, initializer, false); //var mr = GetMemberRef(name); member.index = _memberFuncs.Set(name, member); }
public virtual bool CanStoreValue(ExecContext context, ITypeDef valueType) { //if (valueType is TypeDef) { // return null == (valueType as TypeDef).IsNull(); //} if (valueType.IsNull()) { return(true); } TypeDef_Function funcValueType = valueType as TypeDef_Function; if (null == funcValueType) { return(false); } if (!retType.Equals(IntrinsicTypeDefs.VOID) && !retType.CanStoreValue(context, funcValueType.retType)) { return(false); } if (null != classType) { if (null == funcValueType.classType || !classType.CanStoreValue(context, funcValueType.classType)) { return(false); } // This is the point of isStatic in this class. This is saying, "I can save a reference to a class member function only if it is static." } else if (null != funcValueType.classType && !funcValueType.isStaticMember) { return(false); } // Mismatch if other's max args exceeds our max args. if (argTypes.Count > funcValueType.argTypes.Count) { return(false); } // Mismatch if we have fewer min args than they do. // (Meaning we could be called with fewer arguments than they have default values for.) if (minArgs < funcValueType.minArgs) { return(false); } // Make sure that for every argument WE have, THEIR argument's type matches. for (int ii = 0; ii < argTypes.Count; ++ii) { if (!funcValueType.argTypes[ii].CanStoreValue(context, argTypes[ii])) { return(false); } } return(true); }
// NOTE: isStatic = true has never been tested. Library functions are static but are neither flagged as static nor as class members, // so references can be saved to them by users already. public FunctionValue_Host(ITypeDef _retType, List <ITypeDef> _argTypes, EvaluateDelegate _Evaluate, bool _varargs = false, TypeDef_Class classType = null, bool isStatic = false, List <Expr_Literal> defaultArgVals = null) { argDefaultValues = defaultArgVals; BuildArgHasDefaults(_argTypes.Count); valType = TypeFactory.GetTypeDef_Function(_retType, _argTypes, minArgs, _varargs, classType, true, isStatic); Evaluate = _Evaluate; }
public override bool CanStoreValue(ExecContext context, ITypeDef valueType) { if (valueType is TypeDef_Enum) { return(((TypeDef_Enum)valueType).className == className); } return(false); }
// *************************************************************************** // Type functions. // *************************************************************************** public bool CreateAlias(string alias, ITypeDef typeDefIn) { if (_types.ContainsKey(alias)) { return(false); } _types.Add(alias, typeDefIn); return(true); }
public bool UpdateAlias(string alias, ITypeDef typeDefIn) { if (!_types.ContainsKey(alias)) { return(false); } _types[alias] = typeDefIn; return(true); }
public Variable Set(string nameIn, ITypeDef typeIn, object valueIn = null) { Pb.Assert(null != typeIn, "Can't have a variable without a type."); name = nameIn; type = typeIn; value = valueIn; unique = false; return(this); }
// Use this one for class members, both regular and static. // Note: statics could be stored as uniques, but everything works // atm. If it aint broke, don't fix it. public VarStackRef(ITypeDef typeDefIn, int callIx, MemberRef memRef) { errorType = ErrorType.None; typeDef = typeDefIn; callIndexOffset = callIx; varIndex = -1; memberRef = memRef; isGlobal = false; variable = null; }
// Convenience function for registering a List<> with a given type, because this gets done a number of times. public ClassDef RegisterIfUnregisteredList(ITypeDef valueType) { List <ITypeDef> genericTypes = new List <ITypeDef>(); genericTypes.Add(valueType); TypeDef_Class listTypeDef = TypeFactory.GetTypeDef_Class("List", genericTypes, false); return(engine.defaultContext.RegisterIfUnregisteredTemplate(listTypeDef)); }
// Use this one for non-unique variables on the varStack. public VarStackRef(ITypeDef typeDefIn, int callIx, int ix) { errorType = ErrorType.None; typeDef = typeDefIn; callIndexOffset = callIx; varIndex = ix; memberRef = MemberRef.invalid; isGlobal = false; variable = null; }
// This is for uniques, both globals and those on the stack. public VarStackRef(Variable uniqueVariable, bool global) { errorType = ErrorType.None; callIndexOffset = -9000; varIndex = -1; isGlobal = global; memberRef = MemberRef.invalid; typeDef = uniqueVariable.type; variable = uniqueVariable; variable.unique = true; }
// This creates an invalid VarStackRef. public VarStackRef(ErrorType error) { Pb.Assert(error != ErrorType.None); errorType = error; callIndexOffset = -9000; varIndex = -1; isGlobal = false; memberRef = MemberRef.invalid; typeDef = null; variable = null; }
public static TypeDef_Function GetTypeDef_Function(ITypeDef retType, List <ITypeDef> argTypes, int minArgs, bool _varargs, TypeDef_Class classType, bool isConst, bool isStatic) { if (minArgs < 0) { minArgs = argTypes.Count; } string args = ""; for (int ii = 0; ii < argTypes.Count; ++ii) { string defaultValueString = ""; if (ii >= minArgs) { defaultValueString = " ?"; } args += (ii == 0 ? "" : ", ") + argTypes[ii] + defaultValueString; } string classPart = ""; if (null != classType) { classPart = ":" + classType.className; } string name = "function" + classPart + "<" + retType + "(" + args + ")>"; if (_varargs) { name = name + " varargs"; } if (isStatic) { name = name + " static"; } if (isConst) { name = name + " const"; } if (_typeRegistry.ContainsKey(name)) { return(_typeRegistry[name] as TypeDef_Function); } TypeDef_Function newDef = new TypeDef_Function(retType, argTypes, minArgs, _varargs, classType, isConst, isStatic); #if PEBBLE_TRACETYPES Console.WriteLine("Registering new function type: " + name); #endif _typeRegistry.Add(name, newDef); return(newDef); }
internal TypeDef_Function(ITypeDef _retType, List <ITypeDef> _argTypes, int _minArgs, bool _varargs, TypeDef_Class classTypeIn, bool _isConst, bool _isStaticFunction) { retType = _retType; argTypes = _argTypes; minArgs = _minArgs; varargs = _varargs; isConst = _isConst; classType = classTypeIn; isStaticMember = _isStaticFunction; Pb.Assert(!_varargs || minArgs == _argTypes.Count, "internal error: function cannot be both varArgs and have arguments with default values."); }
public bool CreateGlobal(string symbol, ITypeDef type, object value = null) { Variable existing = stack.GetGlobalVariable(symbol); // existence check if (null != existing) { return(false); } VarStackRef vsr = stack.AddVariable(symbol, true, type, value); return(null != stack.GetVarAtIndex(vsr)); // DoesVarExist }
//public override bool Equals(object obj) { // throw new InvalidProgramException("INTERNAL ERROR: Attempt to use type before it has been evaluated. (Equals)"); //} public override ITypeDef Resolve(ExecContext context, ref bool error) { if (name == "void") { return(IntrinsicTypeDefs.VOID); } ITypeDef def = context.GetTypeByName(name); if (null == def) { context.engine.LogCompileError(ParseErrorType.TypeNotFound, "Type '" + name + "' not found."); error = true; return(null); } if (null == _templateTypes) { if (_isConst && !def.IsConst()) { return(def.Clone(true)); } return(def); } // If we have template types, then we must be a TypeDef_Class. List <ITypeDef> genericTypes = new List <ITypeDef>(); for (int ii = 0; ii < _templateTypes.Count; ++ii) { genericTypes.Add(_templateTypes[ii].Resolve(context, ref error)); } if (error) { return(null); } //TypeDef_Class result = new TypeDef_Class(name, genericTypes, _isConst); TypeDef_Class result = TypeFactory.GetTypeDef_Class(name, genericTypes, _isConst); if (null == context.RegisterIfUnregisteredTemplate(result)) { error = true; } return(result); }
public virtual ITypeDef ResolveTemplateTypes(List <ITypeDef> genericTypes, ref bool modified) { List <ITypeDef> args = new List <ITypeDef>(); for (int ii = 0; ii < argTypes.Count; ++ii) { args.Add(argTypes[ii].ResolveTemplateTypes(genericTypes, ref modified)); } ITypeDef newRetType = retType.ResolveTemplateTypes(genericTypes, ref modified); if (null != classType) { classType.ResolveTemplateTypes(genericTypes, ref modified); } return(TypeFactory.GetTypeDef_Function(newRetType, args, minArgs, varargs, classType, isConst, isStaticMember)); }
public bool Comparable(ExecContext context, ITypeDef other) { if (!(other is TypeDef_Class)) { return(false); } if (Equals(other)) { return(true); } TypeDef_Class otherClassType = other as TypeDef_Class; return(null != context.DetermineAncestor(this, otherClassType)); }
public virtual bool CanStoreValue(ExecContext context, ITypeDef valueType) { if (valueType is TypeDef && null == ((TypeDef)valueType).GetHostType()) { return(true); } TypeDef_Class classValueType = valueType as TypeDef_Class; if (null == classValueType) { return(false); } if (!context.IsChildClass(context.GetClass(className), context.GetClass(classValueType.className))) { return(false); } // If neither has generic types, we match. if (null == classValueType._genericTypes && null == _genericTypes) { return(true); } // If only one has generic types, we do not. if (null == classValueType._genericTypes || null == _genericTypes) { return(false); } // If they don't have the same number, we do not. if (classValueType._genericTypes.Count != _genericTypes.Count) { return(false); } for (int ii = 0; ii < _genericTypes.Count; ++ii) { if (_genericTypes[ii] != classValueType._genericTypes[ii]) { return(false); } } return(true); }
// Only called by the context. public void Initialize() { if (null != _fields) { return; } // 1) fields. _fields = new MemberList(); if (null != parent) { for (int ii = 0; ii < parent._fields.Count; ++ii) { ClassMember member = parent._fields.Get(ii); bool modified = false; ITypeDef resolvedType = parent.IsGeneric() ? member.typeDef.ResolveTemplateTypes(typeDef.genericTypes, ref modified) : member.typeDef; ClassMember newMember = new ClassMember(member.name, resolvedType, member.initializer, member.isGetonly); newMember.index = _fields.Add(member.name, newMember); } } // 2) Functions _memberFuncs = new MemberList(); if (null != parent) { for (int ii = 0; ii < parent._memberFuncs.Count; ++ii) { ClassMember member = parent._memberFuncs.Get(ii); bool modified = false; ITypeDef resolvedType = parent.IsGeneric() ? member.typeDef.ResolveTemplateTypes(typeDef.genericTypes, ref modified) : member.typeDef; ClassMember newMember = new ClassMember(member.name, resolvedType, member.initializer, member.isGetonly); newMember.index = _memberFuncs.Add(member.name, newMember); } vftableVars = new List <Variable>(parent.vftableVars); } else { vftableVars = new List <Variable>(); } // 3) Statics aren't copied. _statics = new MemberList(); staticVars = new List <Variable>(); }
public static ITypeDef GetConstVersion(ITypeDef original) { if (original.IsConst()) { return(original); } string constName = original.GetName() + " const"; if (_typeRegistry.ContainsKey(constName)) { return(_typeRegistry[constName]); } ITypeDef result = original.Clone(true); _typeRegistry.Add(constName, result); return(result); }
public string GetDebugString(string name) { string result = ""; result += retType.ToString() + " " + name + (null != classType ? ":" + classType.className : "") + "("; for (int iArg = 0; iArg < argTypes.Count; ++iArg) { ITypeDef argdef = argTypes[iArg] as ITypeDef; if (0 != iArg) { result += ", "; } result += argdef.ToString() + (iArg >= minArgs ? "?" : ""); } if (varargs) { result += "[, ...]"; } result += ");\n"; return(result); }
public PebbleEnum(ExecContext context, string _enumName, ITypeDef valueTypeIn) { enumName = _enumName; valueType = valueTypeIn; // Apparently need to register non-const first. ITypeDef nonConstEnumType = TypeFactory.GetTypeDef_Enum(_enumName, false); enumType = (TypeDef_Enum)TypeFactory.GetConstVersion(nonConstEnumType); _classDef = new ClassDef_Enum(this, _enumName, enumType); context.RegisterClass(_classDef); _classDef.childAllocator = () => { return(new ClassValue_Enum()); }; _classDef.Initialize(); //don't think this is needed _classDef.AddMemberLiteral("enumName", IntrinsicTypeDefs.CONST_STRING, _enumName, false); _classDef.AddMember("name", IntrinsicTypeDefs.CONST_STRING); _classDef.AddMember("value", valueType.Clone(true), null, false, true); { FunctionValue_Host.EvaluateDelegate eval = (_context, args, thisScope) => { ClassValue cv = thisScope as ClassValue; return(enumName + "::" + cv.Get(mrName).value); }; FunctionValue newValue = new FunctionValue_Host(IntrinsicTypeDefs.STRING, new ArgList { }, eval, false, _classDef.typeDef); _classDef.AddMemberLiteral("ThisToString", newValue.valType, newValue, false); } _classDef.FinalizeClass(context); if (mrName.isInvalid) { mrName = _classDef.GetMemberRef(null, "name", ClassDef.SEARCH.NORMAL); mrValue = _classDef.GetMemberRef(null, "value", ClassDef.SEARCH.NORMAL); } }
public VarStackRef AddVariable(string name, bool global, ITypeDef type, object value = null) { Variable var; if (global) { var = new Variable(name, type, value); _globals.Set(name, var); return(new VarStackRef(var, true)); } if (_varStack.Count == _varCount) { var = new Variable(name, type, value); _varStack.Add(var); } else { var = _varStack[_varCount]; if (null == var) { var = new Variable(name, type, value); _varStack[_varCount] = var; } else { var.Set(name, type, value); } } ++_varCount; #if PEBBLE_TRACESTACK TraceLog("AddVariable " + type.ToString() + " " + name + "[" + (_varCount - 1) + "] = <" + value + ">"); #endif return(new VarStackRef(type, -1, _varCount - _callStack[_callCount - 1].varStackStart - 1)); }
// D B A // G E B A // This is specifically for the conditional operator. // typeof(true?D:G) is B public ITypeDef GetMostCommonType(ITypeDef typeA, ITypeDef typeB) { bool aIsClass = typeA is TypeDef_Class; if (aIsClass) { bool bIsClass = typeB is TypeDef_Class; if (bIsClass) { TypeDef_Class classTypeA = typeA as TypeDef_Class; TypeDef_Class classTypeB = typeB as TypeDef_Class; return(GetMostCommonType(classTypeA, classTypeB)); } } // If they aren't both classes then they must be equal or they // have no commonality. if (typeA.Equals(typeB)) { return(typeA); } return(null); }
/// <summary> /// Builds a new type from the provided list of properties. The new type implements IObjectAccessor interface /// </summary> /// <param name="typeDef">Type definition with list of property names and corresponding types.</param> /// <returns>Newly created type</returns> public static Type MakeType(ITypeDef typeDef) { if (typeDef == null) throw new ArgumentNullException("typeDef"); string typeName = typeDef.Name; if (string.IsNullOrEmpty(typeName)) typeName = MakeUniqueName(); s_lock.EnterWriteLock(); try { TypeBuilder tb = s_mb.DefineType(typeName, TypeAttributes.Public); tb.SetParent(typeof(ObjectAccessorBase<>).MakeGenericType(tb)); int order = 0; foreach (var fb in typeDef.PropertyDefList.Select(entry => tb.DefineField(entry.Key, entry.Value.ResolveType(), FieldAttributes.Public))) AddOrderAttribute(fb, order++); return tb.CreateType(); } finally { s_lock.ExitWriteLock(); } }
public static Type ResolveTypeDef(ITypeDef td) { return GetType(td.Name) ?? MakeType(td); }
// Call this one to create a variable *during execution*. // Doesn't do error checking, doesn't care if variable already exists. // If you aren't sure what you are doing, you probably want to use CreateGlobal. public Variable CreateEval(string symbol, ITypeDef type, object value = null, bool isGlobal = false) { VarStackRef vsr = stack.AddVariable(symbol, isGlobal, type, value); return(stack.GetVarAtIndex(vsr)); }