Exemple #1
0
        /// <summary>
        /// Creates a rule - metadata that allows invocation of a function on
        /// </summary>
        private void RuleDeclaration()
        {
            if (_EnclosingCompiler != null)
            {
                throw new CompilerException(Tokens.Peek(), "Rules must be globally scoped.");
            }
            Token triggerName = Tokens.Consume(IDENTIFIER, "Rule declarations must begin with a named trigger.");
            List <RuleCondition> conditions = new List <RuleCondition>();

            // rule conditions
            while (!Tokens.Match(RIGHT_BRACKET))
            {
                Token contextVariableName  = Tokens.Consume(IDENTIFIER, "Rule must contain list of comparison expressions (missing identifier).");
                Token comparisonOperation  = Tokens.Advance(); // we will check validity of this token after consuming the value
                Token contextVariableValue = Tokens.Consume(NUMBER, "Rule must contain list of comparison expressions (missing value)");
                switch (comparisonOperation.Type)
                {
                case BANG_EQUAL:
                    // conditions.Add(RuleCondition.ConditionNotEquals(contextVariableName.Lexeme, contextVariableValue.LiteralAsNumber));
                    throw new CompilerException(Tokens.Peek(), "Rule must contain list of comparison expressions (can't use != operator).");

                case EQUAL:
                case EQUAL_EQUAL:
                    conditions.Add(RuleCondition.ConditionEquals(contextVariableName.Lexeme, contextVariableValue.LiteralAsNumber));
                    break;

                case GREATER:
                    conditions.Add(RuleCondition.ConditionGreaterThan(contextVariableName.Lexeme, contextVariableValue.LiteralAsNumber));
                    break;

                case GREATER_EQUAL:
                    conditions.Add(RuleCondition.ConditionGreaterThanOrEqual(contextVariableName.Lexeme, contextVariableValue.LiteralAsNumber));
                    break;

                case LESS:
                    conditions.Add(RuleCondition.ConditionLessThan(contextVariableName.Lexeme, contextVariableValue.LiteralAsNumber));
                    break;

                case LESS_EQUAL:
                    conditions.Add(RuleCondition.ConditionLessThanOrEqual(contextVariableName.Lexeme, contextVariableValue.LiteralAsNumber));
                    break;

                default:
                    throw new CompilerException(Tokens.Peek(), "Rule must contain list of comparison expressions (missing operator).");
                }
            }
            if (Tokens.Peek().Type == FUNCTION && Tokens.Peek(1).Type == IDENTIFIER)
            {
                string functionName = Tokens.Peek(1).Lexeme;
                _Rules.Add(new Rule(BitString.GetBitStr(triggerName.Lexeme), BitString.GetBitStr(functionName), conditions.ToArray()));
            }
            else
            {
                throw new CompilerException(Tokens.Peek(), "Rule declaration must be followed by function.");
            }
        }
        private GearsNativeWrapper(Type wrappedType, bool wrapAllPublicFields = false)
        {
            WrappedType = wrappedType;
            BindingFlags binding = BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance;

            FieldInfo[] fields = wrappedType.GetFields(binding);
            foreach (FieldInfo info in fields)
            {
                LoxFieldAttribute attr = info.GetCustomAttribute <LoxFieldAttribute>();
                if (!wrapAllPublicFields && attr == null)
                {
                    continue;
                }
                ulong name = BitString.GetBitStr(attr?.Name ?? info.Name);
                if (NameExists(name))
                {
                    Tracer.Warn($"GearsNativeWrapper: {wrappedType.Name}.{info.Name} is masked by a field, method, or property named '{BitString.GetBitStr(name)}'.");
                    continue;
                }
                _Fields.Add(name, info);
            }
            MethodInfo[] methods = wrappedType.GetMethods(binding).Where(d => !d.IsSpecialName).ToArray();
            foreach (MethodInfo info in methods)
            {
                LoxFieldAttribute attr = info.GetCustomAttribute <LoxFieldAttribute>();
                if (!wrapAllPublicFields && attr == null)
                {
                    continue;
                }
                ulong name = BitString.GetBitStr(attr?.Name ?? info.Name);
                if (NameExists(name))
                {
                    Tracer.Warn($"GearsNativeWrapper: {wrappedType.Name}.{info.Name} is masked by a field, method, or property named '{BitString.GetBitStr(name)}'.");
                    continue;
                }
                _Methods.Add(name, info);
            }
            PropertyInfo[] properties = wrappedType.GetProperties(binding);
            foreach (PropertyInfo info in properties)
            {
                LoxFieldAttribute attr = info.GetCustomAttribute <LoxFieldAttribute>();
                if (!wrapAllPublicFields && attr == null)
                {
                    continue;
                }
                ulong name = BitString.GetBitStr(attr?.Name ?? info.Name);
                if (NameExists(name))
                {
                    Tracer.Warn($"GearsNativeWrapper: {wrappedType.Name}.{info.Name} is masked by a field, method, or property named '{BitString.GetBitStr(name)}'.");
                    continue;
                }
                _Properties.Add(name, info);
            }
        }
Exemple #3
0
        // === Rules =================================================================================================
        // ===========================================================================================================

        internal IEnumerable <string> GetRuleMatches(string triggerName, RuleInvocationContext context)
        {
            ulong triggerBitString = BitString.GetBitStr(triggerName);

            for (int i = 0; i < Rules.Length; i++)
            {
                if (Rules[i].IsTrue(triggerBitString, context))
                {
                    yield return(BitString.GetBitStr(Rules[i].Result));
                }
            }
        }
Exemple #4
0
        private int MakeBitStrConstant(string value)
        {
            ulong bitstr = BitString.GetBitStr(value);

            if (_TempOptimizedStrings.TryGetValue(bitstr, out string optimized))
            {
                if (optimized != value)
                {
                    throw new CompilerException(Tokens.Previous(), $"String collision: '{value}' != '{optimized}'. First 10 characters of all identifiers must be distinct.");
                }
            }
            _TempOptimizedStrings[bitstr] = value;
            return(MakeValueConstant(bitstr));
        }
Exemple #5
0
    internal partial class Gears { // support for native c# calling lox script functions.
        /// <summary>
        /// Calls a LoxScript function from native code, passing arguments.
        /// If the function call was successful, returns true, and returnValue will be the returned value from the function, if any.
        /// If the function call was not successful, returns false, and returnValue will be an error string.
        /// </summary>
        internal bool CallGearsFunction(string fnName, out object returned, params object[] args)
        {
            ulong name = BitString.GetBitStr(fnName);

            return(CallGearsFunction(name, out returned, args));
        }
Exemple #6
0
        internal bool CallGearsFunction(ulong name, out object returned, params object[] args)
        {
            if (!Globals.TryGet(name, out GearsValue fnValue) || !fnValue.IsObjPtr)
            {
                // error: no function with that name.
                returned = $"Error: no function with name '{BitString.GetBitStr(name)}'.";
                return(false);
            }
            GearsObj fnObject = fnValue.AsObject(this);

            if (fnObject is GearsObjFunction fnFunction)
            {
                if (fnFunction.Arity != args.Length)
                {
                    // error: wrong arity.
                    returned = $"Error: called '{BitString.GetBitStr(name)}' with wrong arity (passed arity is '{args?.Length ?? 0}').";
                    return(false);
                }
            }
            Push(fnValue);
            for (int i = 0; i < (args?.Length ?? 0); i++)
            {
                object arg     = args[i];
                Type   argType = arg?.GetType() ?? null;
                if (arg == null)
                {
                    Push(GearsValue.NilValue);
                }
                else if (GearsNativeWrapper.IsNumeric(argType))
                {
                    double fieldValue = Convert.ToDouble(arg);
                    Push(new GearsValue(fieldValue));
                }
                else if (argType == typeof(bool))
                {
                    bool fieldValue = Convert.ToBoolean(arg);
                    Push(fieldValue ? GearsValue.TrueValue : GearsValue.FalseValue);
                }
                else if (argType == typeof(string))
                {
                    string fieldValue = Convert.ToString(arg);
                    if (fieldValue == null)
                    {
                        Push(GearsValue.NilValue);
                    }
                    else
                    {
                        Push(GearsValue.CreateObjPtr(HeapAddObject(new GearsObjString(fieldValue))));
                    }
                }
                else if (argType.IsSubclassOf(typeof(object)))
                {
                    if (arg == null)
                    {
                        Push(GearsValue.NilValue);
                    }
                    else
                    {
                        Push(GearsValue.CreateObjPtr(HeapAddObject(new GearsObjInstanceNative(this, arg))));
                    }
                }
                else
                {
                    // error: could not pass arg of this type
                    returned = $"Error: called '{BitString.GetBitStr(name)}' with argument of type '{argType.Name}' as parameter {i}. Gears could not interpret this argument.";
                    return(false);
                }
            }
            Call(args?.Length ?? 0);
            Run();
            returned = LastReturnValue; // the return value
            // todo: process return value?
            return(true);
        }
Exemple #7
0
        internal string ReadConstantValueAsBitStr(int offset)
        {
            GearsValue value = ReadConstantValue(offset);

            return(BitString.GetBitStr((ulong)value));
        }
Exemple #8
0
        // --- Can probably merge a ton of code from the three call methods ---

        private void CallInvoke()
        {
            int        argCount    = ReadByte();
            ulong      methodName  = (ulong)ReadConstant();
            GearsValue receiverPtr = Peek(argCount);

            if (!receiverPtr.IsObjPtr)
            {
                throw new GearsRuntimeException(Chunk.LineAt(_IP), "Attempted invoke to non-pointer.");
            }
            GearsObj obj = receiverPtr.AsObject(this);

            if (obj is GearsObjInstance instance)
            {
                if (instance.TryGetField(methodName, out GearsValue value))
                {
                    if (!value.IsObjPtr)
                    {
                        throw new GearsRuntimeException(Chunk.LineAt(_IP), "Attempted call to non-pointer.");
                    }
                    GearsObj objFn = HeapGetObject(value.AsObjPtr);
                    if (objFn is GearsObjFunction function)
                    {
                        if (function.Arity != argCount)
                        {
                            throw new GearsRuntimeException(Chunk.LineAt(_IP), $"{function} expects {function.Arity} arguments but was passed {argCount}.");
                        }
                        int ip = function.IP;
                        int bp = _SP - (function.Arity + 1);
                        PushFrame(new GearsCallFrame(function, ip, bp));
                    }
                    else if (objFn is GearsObjFunctionNative native)
                    {
                        if (native.Arity != argCount)
                        {
                            throw new GearsRuntimeException(Chunk.LineAt(_IP), $"{native} expects {native.Arity} arguments but was passed {argCount}.");
                        }
                        GearsValue[] args = new GearsValue[argCount];
                        for (int i = argCount - 1; i >= 0; i--)
                        {
                            args[i] = Pop();
                        }
                        Pop(); // pop the function signature
                        Push(native.Invoke(args));
                    }
                    else
                    {
                        throw new GearsRuntimeException(Chunk.LineAt(_IP), $"Could not resolve method {methodName} in {instance}.");
                    }
                }
                else if (instance is GearsObjInstanceLox instanceLox)
                {
                    InvokeFromClass(argCount, methodName, receiverPtr, instanceLox.Class);
                }
                else
                {
                    throw new GearsRuntimeException(Chunk.LineAt(_IP), $"{instance} does not have a public method named '{BitString.GetBitStr(methodName)}'.");
                }
                return;
            }
            throw new GearsRuntimeException(Chunk.LineAt(_IP), "Attempted invoke to non-instance.");
        }
Exemple #9
0
        /// <summary>
        /// Runs the script from top to bottom.
        /// </summary>
        private bool RunOne()
        {
            LastReturnValue = GearsValue.NilValue;
            while (true)
            {
                EGearsOpCode instruction = (EGearsOpCode)ReadByte();
                switch (instruction)
                {
                case OP_LOAD_CONSTANT:
                    Push(ReadConstant());
                    break;

                case OP_LOAD_STRING:
                    Push(GearsValue.CreateObjPtr(HeapAddObject(new GearsObjString(ReadConstantString()))));
                    break;

                case OP_LOAD_FUNCTION: {
                    int arity                = ReadByte();
                    int address              = ReadShort();
                    int upvalueCount         = ReadByte();
                    GearsObjFunction closure = new GearsObjFunction(Chunk, arity, upvalueCount, address);
                    for (int i = 0; i < upvalueCount; i++)
                    {
                        bool isLocal = ReadByte() == 1;
                        int  index   = ReadByte();
                        if (isLocal)
                        {
                            int location = _OpenFrame.BP + index;
                            closure.Upvalues[i] = CaptureUpvalue(location);
                        }
                        else
                        {
                            closure.Upvalues[i] = _OpenFrame.Function.Upvalues[index];
                        }
                    }
                    Push(GearsValue.CreateObjPtr(HeapAddObject(closure)));
                }
                break;

                case OP_NIL:
                    Push(GearsValue.NilValue);
                    break;

                case OP_TRUE:
                    Push(GearsValue.TrueValue);
                    break;

                case OP_FALSE:
                    Push(GearsValue.FalseValue);
                    break;

                case OP_POP:
                    Pop();
                    break;

                case OP_GET_LOCAL: {
                    int slot = ReadShort();
                    Push(StackGet(slot + _BP));
                }
                break;

                case OP_SET_LOCAL: {
                    int slot = ReadShort();
                    StackSet(slot + _BP, Peek());
                }
                break;

                case OP_GET_GLOBAL: {
                    ulong name = (ulong)ReadConstant();
                    if (!Globals.TryGet(name, out GearsValue value))
                    {
                        throw new GearsRuntimeException(Chunk.LineAt(_IP), $"Undefined variable '{BitString.GetBitStr(name)}'.");
                    }
                    Push(value);
                }
                break;

                case OP_DEFINE_GLOBAL: {
                    ulong name = (ulong)ReadConstant();
                    Globals.Set(name, Peek());
                    Pop();
                }
                break;

                case OP_SET_GLOBAL: {
                    ulong name = (ulong)ReadConstant();
                    if (!Globals.ContainsKey(name))
                    {
                        throw new GearsRuntimeException(Chunk.LineAt(_IP), $"Undefined variable '{BitString.GetBitStr(name)}'.");
                    }
                    Globals.Set(name, Peek());
                    break;
                }

                case OP_GET_UPVALUE: {
                    int             slot    = ReadShort();
                    GearsObjUpvalue upvalue = _OpenFrame.Function.Upvalues[slot];
                    if (upvalue.IsClosed)
                    {
                        Push(upvalue.Value);
                    }
                    else
                    {
                        Push(StackGet(upvalue.OriginalSP));
                    }
                }
                break;

                case OP_SET_UPVALUE: {
                    int             slot    = ReadShort();
                    GearsObjUpvalue upvalue = _OpenFrame.Function.Upvalues[slot];
                    if (upvalue.IsClosed)
                    {
                        upvalue.Value = Peek();
                    }
                    else
                    {
                        StackSet(upvalue.OriginalSP, Peek());
                    }
                }
                break;

                case OP_GET_PROPERTY: {
                    GearsObjInstance instance = GetObjectFromPtr <GearsObjInstance>(Peek());
                    ulong            name     = (ulong)ReadConstant(); // property name
                    if (instance.TryGetField(name, out GearsValue value))
                    {
                        Pop();         // instance
                        Push(value);   // property value
                        break;
                    }
                    if (instance is GearsObjInstanceLox loxInstance && BindLoxMethod(loxInstance.Class, name))
                    {
                        break;
                    }
                    throw new GearsRuntimeException(Chunk.LineAt(_IP), $"Undefined property or method '{name}'.");
                }

                case OP_SET_PROPERTY: {
                    GearsObjInstance instance = GetObjectFromPtr <GearsObjInstance>(Peek(1));
                    ulong            name     = (ulong)ReadConstant(); // property name
                    GearsValue       value    = Pop();                 // value
                    instance.SetField(name, value);
                    Pop();                                             // ptr
                    Push(value);                                       // value
                }
                break;

                case OP_GET_SUPER: {
                    ulong         name       = (ulong)ReadConstant(); // method/property name
                    GearsObjClass superclass = GetObjectFromPtr <GearsObjClass>(Pop());
                    if (!BindLoxMethod(superclass, name))
                    {
                        throw new GearsRuntimeException(Chunk.LineAt(_IP), $"Could not get {name} in superclass {superclass}");
                    }
                }
                break;

                case OP_EQUAL:
                    Push(AreValuesEqual(Pop(), Pop()));
                    break;

                case OP_GREATER: {
                    if (!Peek(0).IsNumber || !Peek(1).IsNumber)
                    {
                        throw new GearsRuntimeException(Chunk.LineAt(_IP), "Operands must be numbers.");
                    }
                    GearsValue b = Pop();
                    GearsValue a = Pop();
                    Push(a > b);
                }
                break;

                case OP_LESS: {
                    if (!Peek(0).IsNumber || !Peek(1).IsNumber)
                    {
                        throw new GearsRuntimeException(Chunk.LineAt(_IP), "Operands must be numbers.");
                    }
                    GearsValue b = Pop();
                    GearsValue a = Pop();
                    Push(a < b);
                }
                break;

                case OP_BITWISE_AND: {
                    if (!Peek(0).IsNumber || !Peek(1).IsNumber)
                    {
                        throw new GearsRuntimeException(Chunk.LineAt(_IP), "Operands of bitwise operators must be numbers.");
                    }
                    GearsValue b = Pop();
                    GearsValue a = Pop();
                    Push((long)((double)a) & (long)((double)b));
                }
                break;

                case OP_BITWISE_OR: {
                    if (!Peek(0).IsNumber || !Peek(1).IsNumber)
                    {
                        throw new GearsRuntimeException(Chunk.LineAt(_IP), "Operands of bitwise operators must be numbers.");
                    }
                    GearsValue b = Pop();
                    GearsValue a = Pop();
                    Push((long)((double)a) | (long)((double)b));
                }
                break;

                case OP_ADD: {
                    GearsValue b = Pop();
                    GearsValue a = Pop();
                    if (a.IsNumber && b.IsNumber)
                    {
                        Push(a + b);
                    }
                    else if (a.IsObjType <GearsObjString>(this) && b.IsObjType <GearsObjString>(this))
                    {
                        string sa = GetObjectFromPtr <GearsObjString>(a).Value;
                        string sb = GetObjectFromPtr <GearsObjString>(b).Value;
                        Push(GearsValue.CreateObjPtr(HeapAddObject(new GearsObjString(sa + sb))));
                    }
                    else
                    {
                        throw new GearsRuntimeException(Chunk.LineAt(_IP), "Operands of add must be numbers or strings.");
                    }
                }
                break;

                case OP_SUBTRACT: {
                    if (!Peek(0).IsNumber || !Peek(1).IsNumber)
                    {
                        throw new GearsRuntimeException(Chunk.LineAt(_IP), "Operands of subtract must be numbers.");
                    }
                    GearsValue b = Pop();
                    GearsValue a = Pop();
                    Push(a - b);
                }
                break;

                case OP_MULTIPLY: {
                    if (!Peek(0).IsNumber || !Peek(1).IsNumber)
                    {
                        throw new GearsRuntimeException(Chunk.LineAt(_IP), "Operands of multiply must be numbers.");
                    }
                    GearsValue b = Pop();
                    GearsValue a = Pop();
                    Push(a * b);
                }
                break;

                case OP_DIVIDE: {
                    if (!Peek(0).IsNumber || !Peek(1).IsNumber)
                    {
                        throw new GearsRuntimeException(Chunk.LineAt(_IP), "Operands of divide must be numbers.");
                    }
                    GearsValue b = Pop();
                    GearsValue a = Pop();
                    Push(a / b);
                }
                break;

                case OP_NOT:
                    Push(IsFalsey(Pop()));
                    break;

                case OP_NEGATE: {
                    if (!Peek(0).IsNumber)
                    {
                        throw new GearsRuntimeException(Chunk.LineAt(_IP), "Operand of negate must be a number.");
                    }
                    Push(-Pop());
                }
                break;

                case OP_JUMP: {
                    int offset = ReadShort();
                    ModIP(offset);
                }
                break;

                case OP_JUMP_IF_FALSE: {
                    int offset = ReadShort();
                    if (IsFalsey(Peek()))
                    {
                        ModIP(offset);
                    }
                }
                break;

                case OP_LOOP: {
                    int offset = ReadShort();
                    ModIP(-offset);
                }
                break;

                case OP_CALL: {
                    Call(argCount: ReadByte());
                }
                break;

                case OP_INVOKE: {
                    CallInvoke();
                }
                break;

                case OP_SUPER_INVOKE: {
                    CallInvokeSuper();
                }
                break;

                case OP_CLOSE_UPVALUE:
                    CloseUpvalues(_SP - 1);
                    Pop();
                    break;

                case OP_RETURN: {
                    GearsValue result = Pop();
                    CloseUpvalues(_OpenFrame.BP);
                    if (PopFrame())
                    {
                        if (_SP != 0)
                        {
                            throw new GearsRuntimeException(Chunk.LineAt(_IP), $"Error after final return: SP is '{_SP}', not '0'.");
                        }
                        LastReturnValue = result;
                        _IP             = Chunk.SizeCode; // code is complete and no longer running.
                        return(true);
                    }
                    Push(result);
                }
                break;

                case OP_CLASS: {
                    Push(GearsValue.CreateObjPtr(HeapAddObject(new GearsObjClass(ReadConstantString()))));
                }
                break;

                case OP_INHERIT: {
                    if (!Peek(0).IsObjType <GearsObjClass>(this))
                    {
                        throw new GearsRuntimeException(Chunk.LineAt(_IP), "Superclass is not a class.");
                    }
                    GearsObjClass super = GetObjectFromPtr <GearsObjClass>(Peek(1));
                    GearsObjClass sub   = GetObjectFromPtr <GearsObjClass>(Peek(0));
                    foreach (ulong key in super.Methods.AllKeys)
                    {
                        if (!super.Methods.TryGet(key, out GearsValue methodPtr))
                        {
                            throw new GearsRuntimeException(Chunk.LineAt(_IP), "Could not copy superclass method table.");
                        }
                        sub.Methods.Set(key, methodPtr);
                    }
                    Pop();         // pop subclass
                }
                break;

                case OP_METHOD: {
                    DefineMethod();
                }
                break;

                default:
                    throw new GearsRuntimeException(Chunk.LineAt(_IP), $"Unknown opcode {instruction}");
                }
            }
        }
Exemple #10
0
        internal static RuleCondition ConditionGreaterThanOrEqual(string varName, double value)
        {
            ulong varname = BitString.GetBitStr(varName);

            return(new RuleCondition(varname, value, float.MaxValue));
        }
Exemple #11
0
        /*internal static RuleCondition ConditionNotEquals(string varName, double value) {
         *  ulong varname = BitString.GetBitStr(varName);
         *  return new RuleCondition(varname, value - Epsilon * 2, value + Epsilon * 2);
         * }*/

        internal static RuleCondition ConditionLessThan(string varName, double value)
        {
            ulong varname = BitString.GetBitStr(varName);

            return(new RuleCondition(varname, float.MinValue, value - Epsilon * 2));
        }
Exemple #12
0
        internal static RuleCondition ConditionEquals(string varName, double value)
        {
            ulong varname = BitString.GetBitStr(varName);

            return(new RuleCondition(varname, value, value));
        }
Exemple #13
0
 internal void AddNativeObjectToGlobals(string name, object obj)
 {
     Globals.Set(BitString.GetBitStr(name), GearsValue.CreateObjPtr(HeapAddObject(new GearsObjInstanceNative(this, obj))));
 }
Exemple #14
0
 /// <summary>
 /// Defines a function that can be called by scripts.
 /// Arity is the number of arguments expected.
 /// </summary>
 internal void AddNativeFunctionToGlobals(string name, int arity, GearsFunctionNativeDelegate onInvoke)
 {
     Globals.Set(BitString.GetBitStr(name), GearsValue.CreateObjPtr(HeapAddObject(new GearsObjFunctionNative(name, arity, onInvoke))));
 }
Exemple #15
0
 public override string ToString() => $"[{BitString.GetBitStr(Trigger)} ...] => {Result}()";
 public void SetField(Gears context, object wrappedObject, ulong name, GearsValue value)
 {
     if (_Fields.TryGetValue(name, out FieldInfo fieldInfo))
     {
         if (value.IsNumber)
         {
             if (!IsNumeric(fieldInfo.FieldType))
             {
                 throw new GearsRuntimeException($"Attempted to set {WrappedType.Name}.{fieldInfo.Name} to numeric value.");
             }
             try {
                 fieldInfo.SetValue(wrappedObject, Convert.ChangeType((double)value, fieldInfo.FieldType));
                 return;
             }
             catch (Exception e) {
                 throw new GearsRuntimeException($"Error setting {WrappedType.Name}.{fieldInfo.Name} to {(double)value}: {e.Message}");
             }
         }
         else if (value.IsNil && fieldInfo.FieldType == typeof(string))
         {
             fieldInfo.SetValue(wrappedObject, null);
             return;
         }
         else if (fieldInfo.FieldType == typeof(bool) && value.IsBool)
         {
             fieldInfo.SetValue(wrappedObject, value.IsTrue);
             return;
         }
         else if (value.IsObjPtr)
         {
             GearsObj obj = value.AsObject(context);
             if (fieldInfo.FieldType == typeof(string) && obj is GearsObjString objString)
             {
                 fieldInfo.SetValue(wrappedObject, objString.Value);
                 return;
             }
         }
     }
     else if (_Properties.TryGetValue(name, out PropertyInfo propertyInfo))
     {
         if (!propertyInfo.GetSetMethod().IsPublic)
         {
             throw new GearsRuntimeException($"Unsupported reference: Native class {WrappedType.Name} does not have a public set method for '{BitString.GetBitStr(name)}'.");
         }
         if (value.IsNumber)
         {
             if (!IsNumeric(propertyInfo.PropertyType))
             {
                 throw new GearsRuntimeException($"Attempted to set {WrappedType.Name}.{propertyInfo.Name} to numeric value.");
             }
             try {
                 propertyInfo.SetValue(wrappedObject, Convert.ChangeType((double)value, propertyInfo.PropertyType), null);
                 return;
             }
             catch (Exception e) {
                 throw new GearsRuntimeException($"Error setting {WrappedType.Name}.{propertyInfo.Name} to {(double)value}: {e.Message}");
             }
         }
         else if (value.IsNil && propertyInfo.PropertyType == typeof(string))
         {
             propertyInfo.SetValue(wrappedObject, null, null);
             return;
         }
         else if (propertyInfo.PropertyType == typeof(bool) && value.IsBool)
         {
             propertyInfo.SetValue(wrappedObject, value.IsTrue, null);
             return;
         }
         else if (value.IsObjPtr)
         {
             GearsObj obj = value.AsObject(context);
             if (propertyInfo.PropertyType == typeof(string) && obj is GearsObjString objString)
             {
                 propertyInfo.SetValue(wrappedObject, objString.Value, null);
                 return;
             }
         }
     }
     throw new GearsRuntimeException($"Unsupported native conversion: Error setting {WrappedType.Name}.{BitString.GetBitStr(name)} to {value}.");
 }
Exemple #17
0
 internal RuleInvocationContext AddContext(string varName, double value)
 {
     _Variables[BitString.GetBitStr(varName)] = value;
     return(this);
 }
Exemple #18
0
        private void InvokeFromClass(int argCount, ulong methodName, GearsValue receiverPtr, GearsObjClass objClass)
        {
            if (!objClass.Methods.TryGet(methodName, out GearsValue methodPtr))
            {
                throw new GearsRuntimeException(Chunk.LineAt(_IP), $"{objClass} has no method with name '{BitString.GetBitStr(methodName)}'.");
            }
            if ((!methodPtr.IsObjPtr) || !(HeapGetObject(methodPtr.AsObjPtr) is GearsObjFunction method))
            {
                throw new GearsRuntimeException(Chunk.LineAt(_IP), $"Could not resolve method '{BitString.GetBitStr(methodName)}' in class {objClass}.");
            }
            if (method.Arity != argCount)
            {
                throw new GearsRuntimeException(Chunk.LineAt(_IP), $"{method} expects {method.Arity} arguments but was passed {argCount}.");
            }
            int ip = method.IP;
            int bp = _SP - (method.Arity + 1);

            if (!receiverPtr.IsNil)
            {
                StackSet(bp, receiverPtr); // todo: this wipes out the method object. Is this bad?
            }
            PushFrame(new GearsCallFrame(method, ip, bp));
        }