Exemplo n.º 1
0
 public void MarkValue(GearsValue value)
 {
     // we don't need to collect value types, as they require no heap allocation.
     if (!value.IsObjPtr)
     {
         return;
     }
     MarkObject(value.AsObject(this));
 }
Exemplo n.º 2
0
 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}.");
 }
Exemplo n.º 3
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.");
        }