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); }
public override object GetDefaultValue(ExecContext context) { string name = GetName(); ClassDef classDef = context.GetClass(name); ClassDef_Enum enumDef = classDef as ClassDef_Enum; return(enumDef.enumDef.GetDefaultValue()); }
public static PebbleList AllocateListString(ExecContext context, string debugName = "(List<string> inst)") { if (null == _listClassDef) { _listClassDef = context.GetClass("List<string>"); } PebbleList listinst = (PebbleList)_listClassDef.childAllocator(); listinst.classDef = _listClassDef; listinst.debugName = debugName; return(listinst); }
// List<Child> could be written to a binary file, but then List<Parent> read. // If there is no variable with type List<Parent> in the reading script, it // wouldn't be in the type registry. // This function insures it's in the registry by parsing a little script which // creates a temp variable of the desired type. // It's pretty inefficient to do this, but parsing type names can be very, very // tricky. It wouldn't necessarily be a *better* solution to try to replicate // the parser's code. protected bool EnsureGenericIsRegistered(ExecContext context, string name) { if (null != context.GetClass(name)) { return(true); } List <ParseErrorInst> errors = new List <ParseErrorInst>(); // I don't think there is a way to use a variable name that is *guaranteed* not to already exist, sadly. IExpr expr = context.engine.Parse("{ " + name + " otehunstoeunthnsjthntxheui; }", ref errors, false); return(null != expr && 0 == errors.Count); }
public virtual object GetDefaultValue(ExecContext context) { string name = GetName(); ClassDef parent = context.GetClass(name); ClassValue result = parent.Allocate(context); if (null == result) { return(null); } result.debugName = parent.name + " Inst"; //result.typeDef = this; return(result); }
public bool Read(ExecContext context, PebbleStreamHelper stream, Variable variable) { if (variable.type.IsConst()) { context.SetRuntimeError(RuntimeErrorType.SerializeIntoConst, "Cannot serialize into const variables."); return(false); } if (variable.type.CanStoreValue(context, IntrinsicTypeDefs.BOOL)) { variable.value = reader.ReadBoolean(); } else if (variable.type == IntrinsicTypeDefs.NUMBER) { variable.value = reader.ReadDouble(); } else if (variable.type == IntrinsicTypeDefs.STRING) { variable.value = reader.ReadString(); } else if (variable.type.GetName().StartsWith("List<")) { string listTypeName = reader.ReadString(); if ("null" == listTypeName) { variable.value = null; return(true); } // Is it possible that the specific generic class isn't registered yet. if (!EnsureGenericIsRegistered(context, listTypeName)) { return(false); } ClassDef listDef = context.GetClass(listTypeName); if (null == listDef) { context.SetRuntimeError(RuntimeErrorType.SerializeUnknownType, "Cannot deserialize list type '" + listTypeName + "' because it is unknown."); return(false); } ClassValue listValue = listDef.Allocate(context); PebbleList newlist = listValue as PebbleList; variable.value = listValue; ITypeDef elementType = listDef.typeDef.genericTypes[0]; int count = reader.ReadInt32(); for (int ii = 0; ii < count; ++ii) { Variable newelem = new Variable(null, elementType); if (!Read(context, stream, newelem)) { return(false); } newlist.list.Add(newelem); } } else if (variable.type.GetName().StartsWith("Dictionary<")) { string listTypeName = reader.ReadString(); if ("null" == listTypeName) { variable.value = null; return(true); } // Is it possible that the specific generic class isn't registered yet. if (!EnsureGenericIsRegistered(context, listTypeName)) { return(false); } ClassDef listDef = context.GetClass(listTypeName); if (null == listDef) { context.SetRuntimeError(RuntimeErrorType.SerializeUnknownType, "Cannot deserialize list type '" + listTypeName + "' because it is unknown."); return(false); } ClassValue listValue = listDef.Allocate(context); PebbleDictionary newlist = listValue as PebbleDictionary; variable.value = listValue; ITypeDef keyType = listDef.typeDef.genericTypes[0]; ITypeDef valueType = listDef.typeDef.genericTypes[1]; int count = reader.ReadInt32(); Variable tempKeyVar = new Variable("tempKeyVar", keyType); for (int ii = 0; ii < count; ++ii) { if (!Read(context, stream, tempKeyVar)) { return(false); } Variable newelem = new Variable(null, valueType); if (!Read(context, stream, newelem)) { return(false); } newlist.dictionary.Add(tempKeyVar.value, newelem); } } else if (variable.type is TypeDef_Enum) { string enumName = reader.ReadString(); string valueName = reader.ReadString(); // This happens. ITypeDef streamedType = context.GetTypeByName(enumName); if (null == streamedType) { context.SetRuntimeError(RuntimeErrorType.SerializeUnknownType, "Attempt to load saved enum of unknown type '" + enumName + "'."); return(false); } // I can't get this to happen. if (!(streamedType is TypeDef_Enum)) { context.SetRuntimeError(RuntimeErrorType.SerializeUnknownType, "Type '" + enumName + "' saved as something other than an enum, but attempted to stream into an enum variable."); return(false); } ClassDef enumClassDef = context.GetClass(enumName); Pb.Assert(null != enumClassDef, "Somehow we got a type for an enum but not the def."); ClassDef_Enum enumDef = enumClassDef as ClassDef_Enum; Pb.Assert(null != enumClassDef, "Registered type is enum but def is classdef."); // This happens. ClassValue_Enum cve = enumDef.enumDef.GetValue(valueName); if (null == cve) { context.SetRuntimeError(RuntimeErrorType.EnumValueNotFound, "Enum '" + enumName + "' does not have saved value '" + valueName + "'."); return(false); } variable.value = cve; } else if (variable.type is TypeDef_Class) { TypeDef_Class varType = variable.type as TypeDef_Class; // Get class name. string streamClassName = reader.ReadString(); if ("null" == streamClassName) { variable.value = null; return(true); } ITypeDef streamedType = context.GetTypeByName(streamClassName); if (null == streamedType) { context.SetRuntimeError(RuntimeErrorType.SerializeUnknownType, "Serialized type '" + streamClassName + "' not found."); return(false); } if (!varType.CanStoreValue(context, streamedType)) { context.SetRuntimeError(RuntimeErrorType.SerializeTypeMismatch, "Cannot deserialize a '" + streamClassName + "' into a variable of type '" + varType.GetName() + "'."); return(false); } TypeDef_Class streamedClassType = streamedType as TypeDef_Class; Pb.Assert(null != streamedClassType, "Somehow a streamed type is not a class but *can* be stored in a class type?!"); ClassDef streamedClassDef = context.GetClass(streamClassName); Pb.Assert(null != streamedClassDef, "Somehow we got a type for a class but not the def."); MemberRef serMemRef = streamedClassDef.GetMemberRef(null, "Serialize", ClassDef.SEARCH.NORMAL); if (serMemRef.isInvalid) { context.SetRuntimeError(RuntimeErrorType.SerializeInvalidClass, "Serialize function of class '" + streamClassName + "' not found."); return(false); } ClassValue streamedClassValue = streamedClassDef.Allocate(context); Variable serFuncVar = streamedClassValue.Get(serMemRef); FunctionValue serFuncVal = serFuncVar.value as FunctionValue; serFuncVal.Evaluate(context, new List <object>() { stream }, streamedClassValue); if (context.IsRuntimeErrorSet()) { return(false); } variable.value = streamedClassValue; } else { throw new Exception("Internal error: Unexpected type of value in stream Read."); } return(true); }
/* * public override string ToString() { * string argString = "ARGS"; * return (_isConst ? "const " : "") + "<" + retType + "(" + argString + ")>"; * } */ public override ITypeDef Resolve(ExecContext context, ref bool error) { ITypeDef retValType = retType.Resolve(context, ref error); if (null == retValType) { context.engine.LogCompileError(ParseErrorType.TypeNotFound, "Type '" + retType + "' not found."); error = true; return(null); } if (null != argHasDefaults && argHasDefaults.Count < argTypes.Count) { context.engine.LogCompileError(ParseErrorType.DefaultArgGap, "An argument with a default value is followed by an argument without one."); error = true; return(null); } int minArgs = argTypes.Count; if (null != argHasDefaults) { int firstDefault = -1; for (int ii = 0; ii < argHasDefaults.Count; ++ii) { if (argHasDefaults[ii]) { if (firstDefault < 0) { firstDefault = ii; minArgs = ii; } } else if (firstDefault >= 0) { context.engine.LogCompileError(ParseErrorType.DefaultArgGap, "An argument with a default value is followed by an argument without one."); error = true; return(null); } } } List <ITypeDef> argValTypes = new List <ITypeDef>(); for (int ii = 0; ii < argTypes.Count; ++ii) { ITypeDef argValType = argTypes[ii].Resolve(context, ref error); if (null == argValType) { context.engine.LogCompileError(ParseErrorType.TypeNotFound, "Type '" + argTypes[ii] + "' not found."); error = true; return(null); } argValTypes.Add(argValType); } TypeDef_Class classType = null; if (null != className) { ClassDef classDef = context.GetClass(className); if (null == classDef) { Pb.Assert(false, "Internal error: error resolving class type."); } classType = classDef.typeDef; } var ret = TypeFactory.GetTypeDef_Function(retValType, argValTypes, minArgs, varArgs, classType, _isConst, false); return(ret); }