/// <summary> /// Emits code that calls a method appropriate for the operator /// <paramref name="op"/> on the type <paramref name="type"/>, given the /// operands <paramref name="operands"/>. /// </summary> /// <param name="op">The operation to perform on <paramref /// name="operands"/>.</param> /// <param name="type">The type of the expression.</param> /// <param name="operands">The operands to perform the operation /// <paramref name="op"/> on.</param> private void GenerateCodeForOperation(Operator op, IToken operatorToken, Yarn.IType type, params ParserRuleContext[] operands) { // Generate code for each of the operands, so that their value is // now on the stack. foreach (var operand in operands) { this.Visit(operand); } // Indicate that we are pushing this many items for comparison this.compiler.Emit(OpCode.PushFloat, operatorToken, new Operand(operands.Length)); // Figure out the canonical name for the method that the VM should // invoke in order to perform this work Yarn.IType implementingType = TypeUtil.FindImplementingTypeForMethod(type, op.ToString()); // Couldn't find an implementation method? That's an error! The type // checker should have caught this. if (implementingType == null) { throw new InvalidOperationException($"Internal error: Codegen failed to get implementation type for {op} given input type {type.Name}."); } string functionName = TypeUtil.GetCanonicalNameForMethod(implementingType, op.ToString()); // Call that function. this.compiler.Emit(OpCode.CallFunc, operatorToken, new Operand(functionName)); }
/// <summary> /// Used internally by serialization functions to wrap around the /// SetValue() methods. /// </summary> void SetVariable(string name, Yarn.IType type, string value) { if (type == Yarn.BuiltinTypes.Boolean) { bool newBool; if (bool.TryParse(value, out newBool)) { SetValue(name, newBool); } else { throw new System.InvalidCastException($"Couldn't initialize default variable {name} with value {value} as Bool"); } } else if (type == Yarn.BuiltinTypes.Number) { float newNumber; if (float.TryParse(value, out newNumber)) { // TODO: this won't work for different cultures (e.g. French write "0.53" as "0,53") SetValue(name, newNumber); } else { throw new System.InvalidCastException($"Couldn't initialize default variable {name} with value {value} as Number (Float)"); } } else if (type == Yarn.BuiltinTypes.String) { SetValue(name, value); // no special type conversion required } else { throw new System.ArgumentOutOfRangeException($"Unsupported type {type.Name}"); } }
/// <summary> /// Creates a new instance of the <see cref="Declaration"/> class, /// using the given name, type and default value. /// </summary> /// <param name="name">The name of the new declaration.</param> /// <param name="type">The type of the declaration.</param> /// <param name="defaultValue">The default value of the /// declaration. This must be a string, a number (integer or /// floating-point), or boolean value.</param> /// <param name="description">The description of the new /// declaration.</param> /// <returns>A new instance of the <see cref="Declaration"/> /// class.</returns> public static Declaration CreateVariable(string name, Yarn.IType type, IConvertible defaultValue, string description = null) { if (type is null) { throw new ArgumentNullException(nameof(type)); } if (string.IsNullOrEmpty(name)) { throw new ArgumentException($"'{nameof(name)}' cannot be null or empty.", nameof(name)); } if (defaultValue is null) { throw new ArgumentNullException(nameof(defaultValue)); } // We're all good to create the new declaration. return(new Declaration { Name = name, DefaultValue = defaultValue, Type = type, Description = description, }); }
protected override void Apply() { base.Apply(); // Get all declarations that came from this program var thisProgramDeclarations = new List <Yarn.Compiler.Declaration>(); for (int i = 0; i < serializedDeclarationsProperty.arraySize; i++) { var decl = serializedDeclarationsProperty.GetArrayElementAtIndex(i); if (decl.FindPropertyRelative("sourceYarnAsset").objectReferenceValue != null) { continue; } var name = decl.FindPropertyRelative("name").stringValue; SerializedProperty typeProperty = decl.FindPropertyRelative("typeName"); Yarn.IType type = YarnProjectImporter.SerializedDeclaration.BuiltInTypesList.FirstOrDefault(t => t.Name == typeProperty.stringValue); var description = decl.FindPropertyRelative("description").stringValue; System.IConvertible defaultValue; if (type == Yarn.BuiltinTypes.Number) { defaultValue = decl.FindPropertyRelative("defaultValueNumber").floatValue; } else if (type == Yarn.BuiltinTypes.String) { defaultValue = decl.FindPropertyRelative("defaultValueString").stringValue; } else if (type == Yarn.BuiltinTypes.Boolean) { defaultValue = decl.FindPropertyRelative("defaultValueBool").boolValue; } else { throw new System.ArgumentOutOfRangeException($"Invalid declaration type {type.Name}"); } var declaration = Declaration.CreateVariable(name, type, defaultValue, description); thisProgramDeclarations.Add(declaration); } var output = Yarn.Compiler.Utility.GenerateYarnFileWithDeclarations(thisProgramDeclarations, "Program"); var importer = target as YarnProjectImporter; File.WriteAllText(importer.assetPath, output, System.Text.Encoding.UTF8); AssetDatabase.ImportAsset(importer.assetPath); }
public Value(IType type, IConvertible internalValue) { this.Type = type; this.InternalValue = internalValue; }
public Value(IBridgeableType <IConvertible> type) { this.Type = type; this.InternalValue = type.DefaultValue; }
/// <summary> /// Initializes a new instance of the <see cref="Value"/> class, /// using the specified object. /// </summary> /// <remarks> /// If the <c>value</c> is another <see cref="Value"/>, its contents /// will be copied into the new instance. /// </remarks> /// <throws cref="ArgumentException"> /// Thrown when the <c>value</c> is not a <see cref="Value"/>, string, /// int, float, double, bool, or null. /// </throws> /// <param name="value">The value that this <see cref="Value"/> /// should contain.</param> public Value(Value value) { this.Type = value.Type; this.InternalValue = value.InternalValue; }