Ejemplo n.º 1
0
        /// <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}");
     }
 }
Ejemplo n.º 3
0
        /// <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);
        }
Ejemplo n.º 5
0
 public Value(IType type, IConvertible internalValue)
 {
     this.Type          = type;
     this.InternalValue = internalValue;
 }
Ejemplo n.º 6
0
 public Value(IBridgeableType <IConvertible> type)
 {
     this.Type          = type;
     this.InternalValue = type.DefaultValue;
 }
Ejemplo n.º 7
0
 /// <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;
 }