예제 #1
0
        public static void Compile(JsCompiler compiler, JsClass klass, ObjectMethodId id)
        {
            var type = klass.Type;

            if (!type.IsEnum)
            {
                throw new InvalidOperationException("Type is not enum.");
            }

            switch (id)
            {
            case ObjectMethodId.Equals:
                //TODO: implement Equals for enums here
                JsStruct.Compile(compiler, klass, id);
                break;

            case ObjectMethodId.GetHashCode:
                CompileGetHashCode(compiler, klass);
                break;

            case ObjectMethodId.ToString:
                CompileToString(compiler, klass);
                break;

            default:
                throw new ArgumentOutOfRangeException("id");
            }
        }
예제 #2
0
 public MethodContext(JsCompiler host, JsClass klass, IMethod method, TryCatchBlock[] blocks)
 {
     ProtectedBlocks = blocks;
     Host            = host;
     Class           = klass;
     Method          = method;
 }
예제 #3
0
        private static object GetValue(JsCompiler compiler, IField field, IType valueType)
        {
            var value = field.Value;

            if (value == null)
            {
                throw new InvalidOperationException();
            }
            return(CompileValue(compiler, valueType, value));
        }
예제 #4
0
        private static void CompileToString(JsCompiler compiler, JsClass klass)
        {
            var type = klass.Type;

            CompileValues(compiler, klass);

            var func      = new JsFunction(null);
            var withFlags = type.HasAttribute("System.FlagsAttribute");

            func.Body.Add(new JsText(withFlags ? "return $enum.flags(this);" : "return $enum.stringify(this);"));

            klass.ExtendPrototype(func, "toString");
        }
예제 #5
0
        public static void Compile(JsCompiler compiler, JsClass klass, ObjectMethodId id)
        {
            switch (id)
            {
            case ObjectMethodId.Equals:
                CompileEquals(compiler, klass);
                break;

            case ObjectMethodId.GetHashCode:
                CompileGetHashCode(klass);
                break;

            case ObjectMethodId.ToString:
                // Object.ToString will be used
                break;

            default:
                throw new ArgumentOutOfRangeException("id");
            }
        }
예제 #6
0
        private static void CompileEquals(JsCompiler compiler, JsClass klass)
        {
            var other = "o".Id();

            var func = new JsFunction(null, other.Value);

            func.Body.Add(new JsText("if (o === null || o === undefined) return false;"));

            //TODO: check object type

            JsNode result = null;

            foreach (var field in GetInstanceFields(klass))
            {
                var name  = field.JsName();
                var left  = "this".Id().Get(name);
                var right = other.Get(name);

                JsNode e;
                // primitive and ref types
                if (field.Type.TypeKind != TypeKind.Struct && !field.Type.IsInt64Based())
                {
                    e = left.Op(right, BinaryOperator.Equality);
                }
                else                 // value types, int64 based
                {
                    var objectType = compiler.SystemTypes.Object;
                    var eq         = objectType.Methods.Find("Equals", objectType, objectType);
                    compiler.CompileMethod(eq);
                    e = eq.JsFullName().Id().Call(left, right);
                }

                result = result == null ? e : result.And(e);
            }

            func.Body.Add(result == null ? "false".Id().Return() : result.Return());

            var methodName = ObjectMethods.Find(compiler.SystemTypes.Object, ObjectMethodId.Equals).JsName();

            klass.ExtendPrototype(func, methodName);
        }
예제 #7
0
        private static object CompileValue(JsCompiler compiler, IType type, object value)
        {
            var st = type.SystemType();

            if (st == null)
            {
                throw new ArgumentException("Type is not system");
            }
            switch (st.Code)
            {
            case SystemTypeCode.Int8:
                return(Convert.ToSByte(value, CultureInfo.InvariantCulture));

            case SystemTypeCode.UInt8:
                return(Convert.ToByte(value, CultureInfo.InvariantCulture));

            case SystemTypeCode.Int16:
                return(Convert.ToInt16(value, CultureInfo.InvariantCulture));

            case SystemTypeCode.UInt16:
                return(Convert.ToUInt16(value, CultureInfo.InvariantCulture));

            case SystemTypeCode.Int32:
                return(Convert.ToInt32(value, CultureInfo.InvariantCulture));

            case SystemTypeCode.UInt32:
                return(Convert.ToUInt32(value, CultureInfo.InvariantCulture));

            case SystemTypeCode.Int64:
                return(compiler.CompileInt64(Convert.ToInt64(value, CultureInfo.InvariantCulture)));

            case SystemTypeCode.UInt64:
                return(compiler.CompileUInt64(Convert.ToUInt64(value, CultureInfo.InvariantCulture)));

            default:
                throw new ArgumentException("Invalid type");
            }
        }
예제 #8
0
        private static void CompileValues(JsCompiler compiler, JsClass klass)
        {
            var type = klass.Type;

            var fields = type.GetEnumFields()
                         .Select(x =>
            {
                var value = GetValue(compiler, x, type.ValueType);
                return(new { Name = x.Name, Value = value });
            });

            var    typeName    = type.JsFullName();
            var    valuesField = string.Format("{0}.$$values", typeName);
            object values;

            if (type.ValueType.IsInt64())
            {
                values = new JsArray(fields.Select(x => (object)new JsObject
                {
                    { "name", x.Name },
                    { "value", x.Value },
                }));
            }
            else
            {
                values = new JsObject(fields.Select(x => new KeyValuePair <object, object>(x.Value, x.Name)));
            }

            klass.Add(new JsGeneratedField(valuesField, values));

            var func = new JsFunction(null);

            func.Body.Add(valuesField.Id().Return());

            klass.ExtendPrototype(func, "$values");
        }
예제 #9
0
        private static void CompileGetHashCode(JsCompiler compiler, JsClass klass)
        {
            var type = klass.Type;
            var func = new JsFunction(null);

            var value = "this.$value".Id();

            if (type.ValueType.IsInt64())
            {
                //TODO: inline [U]Int64.GetHashCode implementation
                func.Body.Add(value.Get("GetHashCode").Call().Return());
            }
            else if (!type.ValueType.Is(SystemTypeCode.Int32))
            {
                var int32Type = compiler.SystemTypes.Int32;
                func.Body.Add("$conv".Id().Call(value, type.ValueType.JsTypeCode(), int32Type.JsTypeCode()).Return());
            }
            else
            {
                func.Body.Add(value.Return());
            }

            klass.ExtendPrototype(func, "GetHashCode");
        }
예제 #10
0
 public TypeInfoBuilder(JsCompiler host, JsProgram program)
 {
     _host    = host;
     _program = program;
 }
예제 #11
0
 public BoxingImpl(JsCompiler host)
 {
     _host = host;
 }
예제 #12
0
 public NopCodeProvider(JsCompiler host, JsClass klass, IMethod method)
 {
     _host   = host;
     _klass  = klass;
     _method = method;
 }
예제 #13
0
 public FieldCompiler(JsCompiler host)
 {
     _host = host;
 }
예제 #14
0
 public InternalCallImpl(JsCompiler host)
 {
     _host = host;
 }
예제 #15
0
 public ArrayInterfaceImpl(JsCompiler host)
 {
     _host = host;
 }