Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

Moved operators into the Runtime assembly.

  • Loading branch information...
commit cf523651edf95ba4c36da81a0564233b8e5338df 1 parent bc09b99
@otac0n otac0n authored
View
1  Src/IronJS.Runtime/IronJS.Runtime.CLR2.csproj
@@ -69,6 +69,7 @@
<Compile Include="Objects\RegExpObject.cs" />
<Compile Include="Objects\StringObject.cs" />
<Compile Include="Objects\ValueObject.cs" />
+ <Compile Include="Operators.cs" />
<Compile Include="ParameterStorageType.cs" />
<Compile Include="ParamsMode.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
View
1  Src/IronJS.Runtime/IronJS.Runtime.csproj
@@ -102,6 +102,7 @@
<Compile Include="Objects\RegExpObject.cs" />
<Compile Include="Objects\StringObject.cs" />
<Compile Include="Objects\ValueObject.cs" />
+ <Compile Include="Operators.cs" />
<Compile Include="ParameterStorageType.cs" />
<Compile Include="ParamsMode.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
View
344 Src/IronJS.Runtime/Operators.cs
@@ -0,0 +1,344 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+
+namespace IronJS.Runtime
+{
+ public static class Operators
+ {
+ /// <summary>
+ /// Implements the unary `typeof` operator.
+ /// </summary>
+ public static string typeOf(BoxedValue value)
+ {
+ if (value.IsNumber)
+ {
+ return "number";
+ }
+
+ if (value.IsNull)
+ {
+ return "object";
+ }
+
+ return TypeTags.GetName(value.Tag);
+ }
+
+ /// <summary>
+ /// Implements the unary `!` operator.
+ /// </summary>
+ public static bool not(BoxedValue value)
+ {
+ return !TypeConverter.ToBoolean(value);
+ }
+
+ /// <summary>
+ /// Implements the unary `~` operator.
+ /// </summary>
+ public static double bitCmpl(BoxedValue value)
+ {
+ return (double)~TypeConverter.ToInt32(TypeConverter.ToNumber(value));
+ }
+
+ /// <summary>
+ /// Implements the unary `+` operator.
+ /// </summary>
+ public static BoxedValue plus(BoxedValue value)
+ {
+ return BoxedValue.Box(TypeConverter.ToNumber(value));
+ }
+
+ /// <summary>
+ /// Implements the unary `-` operator.
+ /// </summary>
+ public static BoxedValue minus(BoxedValue o)
+ {
+ return BoxedValue.Box((double)(TypeConverter.ToNumber(o) * -1.0));
+ }
+
+ /// <summary>
+ /// Implements the binary `in` operator.
+ /// </summary>
+ public static bool @in(Environment env, BoxedValue l, BoxedValue r)
+ {
+ if (!r.IsObject)
+ {
+ return env.RaiseTypeError<bool>("Right operand is not a object");
+ }
+ uint index = 0;
+ if (TypeConverter.TryToIndex(l, out index))
+ {
+ return r.Object.Has(index);
+ }
+ string name = TypeConverter.ToString(l);
+ return r.Object.Has(name);
+ }
+
+ /// <summary>
+ /// Implements the binary `instanceof` operator.
+ /// </summary>
+ public static bool instanceOf(Environment env, BoxedValue l, BoxedValue r)
+ {
+ if (!r.IsFunction)
+ {
+ return env.RaiseTypeError<bool>("Right operand is not a function");
+ }
+ if (!l.IsObject)
+ {
+ return false;
+ }
+ return r.Func.HasInstance(l.Object);
+ }
+
+ /// <summary>
+ /// Supports the binary comparison operators.
+ /// </summary>
+ private static bool Compare(BoxedValue l, BoxedValue r, bool rightToLeft, Func<string, string, bool> stringCompare, Func<double, double, bool> numberCompare)
+ {
+ if ((l.Tag == TypeTags.String || l.Tag == TypeTags.SuffixString) &&
+ (r.Tag == TypeTags.String || r.Tag == TypeTags.SuffixString))
+ {
+ return stringCompare(
+ l.Clr.ToString(),
+ r.Clr.ToString());
+ }
+
+ if (l.IsNumber && r.IsNumber)
+ {
+ return numberCompare(
+ l.Number,
+ r.Number);
+ }
+
+ BoxedValue lPrim, rPrim;
+ if (rightToLeft)
+ {
+ rPrim = TypeConverter.ToPrimitive(r, DefaultValueHint.Number);
+ lPrim = TypeConverter.ToPrimitive(l, DefaultValueHint.Number);
+ }
+ else
+ {
+ lPrim = TypeConverter.ToPrimitive(l, DefaultValueHint.Number);
+ rPrim = TypeConverter.ToPrimitive(r, DefaultValueHint.Number);
+ }
+
+
+ if ((lPrim.Tag == TypeTags.String || lPrim.Tag == TypeTags.SuffixString) &&
+ (rPrim.Tag == TypeTags.String || rPrim.Tag == TypeTags.SuffixString))
+ {
+ return stringCompare(
+ lPrim.Clr.ToString(),
+ rPrim.Clr.ToString());
+ }
+
+ var lNum = TypeConverter.ToNumber(lPrim);
+ var rNum = TypeConverter.ToNumber(rPrim);
+ return numberCompare(
+ lNum,
+ rNum);
+ }
+
+ /// <summary>
+ /// Implements the binary `&lt;` operator.
+ /// </summary>
+ public static bool lt(BoxedValue l, BoxedValue r)
+ {
+ return Compare(l, r, false,
+ (a, b) => string.CompareOrdinal(a, b) < 0,
+ (a, b) => a < b);
+ }
+
+ /// <summary>
+ /// Implements the binary `&lt;=` operator.
+ /// </summary>
+ public static bool ltEq(BoxedValue l, BoxedValue r)
+ {
+ return Compare(l, r, true,
+ (a, b) => string.CompareOrdinal(a, b) <= 0,
+ (a, b) => a <= b);
+ }
+
+ /// <summary>
+ /// Implements the binary `&gt;` operator.
+ /// </summary>
+ public static bool gt(BoxedValue l, BoxedValue r)
+ {
+ return Compare(l, r, true,
+ (a, b) => string.CompareOrdinal(a, b) > 0,
+ (a, b) => a > b);
+ }
+
+ /// <summary>
+ /// Implements the binary `&gt;=` operator.
+ /// </summary>
+ public static bool gtEq(BoxedValue l, BoxedValue r)
+ {
+ return Compare(l, r, false,
+ (a, b) => string.CompareOrdinal(a, b) >= 0,
+ (a, b) => a >= b);
+ }
+
+ /// <summary>
+ /// Implements the binary `==` operator.
+ /// </summary>
+ public static bool eq(BoxedValue l, BoxedValue r)
+ {
+ if (Operators.same(l, r))
+ {
+ return true;
+ }
+
+ if (l.IsNull && r.IsUndefined ||
+ l.IsUndefined && r.IsNull)
+ {
+ return true;
+ }
+
+ if (l.IsNumber && r.IsString)
+ {
+ return l.Number == TypeConverter.ToNumber(r);
+ }
+
+ if (l.IsString && r.IsNumber)
+ {
+ return TypeConverter.ToNumber(l) == r.Number;
+ }
+
+ if (l.Tag == TypeTags.Bool)
+ {
+ var newL = BoxedValue.Box(TypeConverter.ToNumber(l));
+ return Operators.eq(newL, r);
+ }
+
+ if (r.Tag == TypeTags.Bool)
+ {
+ var newR = BoxedValue.Box(TypeConverter.ToNumber(r));
+ return Operators.eq(l, newR);
+ }
+
+ if (l.Tag >= TypeTags.Object)
+ {
+ if (r.Tag == TypeTags.SuffixString || r.Tag == TypeTags.String || r.IsNumber)
+ {
+ var newL = TypeConverter.ToPrimitive(l.Object, DefaultValueHint.None);
+ return Operators.eq(newL, r);
+ }
+
+ return false;
+ }
+
+ if (r.Tag >= TypeTags.Object)
+ {
+ if (l.Tag == TypeTags.SuffixString || l.Tag == TypeTags.String || l.IsNumber)
+ {
+ var newR = TypeConverter.ToPrimitive(r.Object, DefaultValueHint.None);
+ return Operators.eq(l, newR);
+ }
+
+ return false;
+ }
+
+ return false;
+ }
+
+ /// <summary>
+ /// Implements the binary `!=` operator.
+ /// </summary>
+ public static bool notEq(BoxedValue l, BoxedValue r)
+ {
+ return !Operators.eq(l, r);
+ }
+
+ /// <summary>
+ /// Implements the binary `===` operator.
+ /// </summary>
+ public static bool same(BoxedValue l, BoxedValue r)
+ {
+ if (l.IsNumber && r.IsNumber)
+ {
+ return l.Number == r.Number;
+ }
+
+ if ((l.Tag == TypeTags.String || l.Tag == TypeTags.SuffixString) &&
+ (r.Tag == TypeTags.String || r.Tag == TypeTags.SuffixString))
+ {
+ return l.Clr.ToString() == r.Clr.ToString();
+ }
+
+ if (l.Tag == r.Tag)
+ {
+ switch (l.Tag)
+ {
+ case TypeTags.Undefined: return true;
+ case TypeTags.Bool: return l.Bool == r.Bool;
+ case TypeTags.Clr:
+ case TypeTags.Function:
+ case TypeTags.Object: return object.ReferenceEquals(l.Clr, r.Clr);
+ default: return false;
+ }
+ }
+
+ return false;
+ }
+
+ /// <summary>
+ /// Implements the binary `!==` operator.
+ /// </summary>
+ public static bool notSame(BoxedValue l, BoxedValue r)
+ {
+ return !Operators.same(l, r);
+ }
+
+ /// <summary>
+ /// Implements the binary `+` operator.
+ /// </summary>
+ public static BoxedValue add(BoxedValue l, BoxedValue r)
+ {
+ if (l.Tag == TypeTags.SuffixString)
+ {
+ var newString = SuffixString.Concat(
+ l.SuffixString,
+ TypeConverter.ToString(TypeConverter.ToPrimitive(r)));
+
+ return BoxedValue.Box(newString);
+ }
+
+ if (l.Tag == TypeTags.String ||
+ r.Tag == TypeTags.String ||
+ r.Tag == TypeTags.SuffixString)
+ {
+ var newString = SuffixString.Concat(
+ TypeConverter.ToString(TypeConverter.ToPrimitive(l)),
+ TypeConverter.ToString(TypeConverter.ToPrimitive(r)));
+
+ return BoxedValue.Box(newString);
+ }
+
+ var lPrim = TypeConverter.ToPrimitive(l);
+ var rPrim = TypeConverter.ToPrimitive(r);
+
+ if (lPrim.Tag == TypeTags.SuffixString)
+ {
+ var newString = SuffixString.Concat(
+ lPrim.SuffixString,
+ TypeConverter.ToString(rPrim));
+
+ return BoxedValue.Box(newString);
+ }
+
+ if (lPrim.Tag == TypeTags.String ||
+ rPrim.Tag == TypeTags.String ||
+ rPrim.Tag == TypeTags.SuffixString)
+ {
+ var newString = SuffixString.Concat(
+ TypeConverter.ToString(lPrim),
+ TypeConverter.ToString(rPrim));
+
+ return BoxedValue.Box(newString);
+ }
+
+ return BoxedValue.Box(TypeConverter.ToNumber(lPrim) + TypeConverter.ToNumber(rPrim));
+ }
+ }
+}
View
74 Src/IronJS/Compiler.ControlFlow.fs
@@ -19,7 +19,7 @@ module internal ControlFlow =
let ifFalse = ctx $ compile ifFalse
let ifTrue, ifFalse =
- if ifTrue.Type <> ifFalse.Type
+ if ifTrue.Type <> ifFalse.Type
then Utils.box ifTrue, Utils.box ifFalse
else ifTrue, ifFalse
@@ -74,7 +74,7 @@ module internal ControlFlow =
let body = ctx $ Context.compile body
Dlr.for' init test incr body break' continue'
-
+
//----------------------------------------------------------------------------
// 12.6.4 for-in
let forIn (ctx:Ctx) label target object' body =
@@ -82,7 +82,7 @@ module internal ControlFlow =
let target = match target with Ast.Var ast -> ast | _ -> target
let pair = Dlr.paramT<Tuple<uint32, MutableSet<string>>> "pair"
-
+
let propertyState = Dlr.paramT<bool> "propertyState"
let propertySet = Dlr.property pair "Item2"
@@ -101,9 +101,9 @@ module internal ControlFlow =
let ctx = {ctx with Labels = labels}
let source = Dlr.paramT<BV> "~source"
- let tempVars =
+ let tempVars =
[ pair; source
- propertyEnumerator; propertyState;
+ propertyEnumerator; propertyState;
indexCurrent; indexLength]
Dlr.block tempVars [
@@ -111,31 +111,31 @@ module internal ControlFlow =
(Dlr.if'
(
- Dlr.Expr.Not (source .-> "IsNull")
+ Dlr.Expr.Not (source .-> "IsNull")
.&&
Dlr.Expr.Not (source .-> "IsUndefined")
)
(Dlr.Fast.block [||] [|
-
- (Dlr.assign pair
- (Dlr.call
+
+ (Dlr.assign pair
+ (Dlr.call
(Utils.Convert.toObject ctx source) "CollectProperties" []))
(Dlr.assign propertyEnumerator (Dlr.call propertySet "GetEnumerator" []))
(Dlr.assign propertyState Dlr.true')
(Dlr.assign indexLength (Dlr.property pair "Item1"))
- (Dlr.loop
+ (Dlr.loop
(break')
(Dlr.labelVoid "~dummyLabel")
(Dlr.true')
(Dlr.blockSimple [
-
- (Dlr.if' propertyState
+
+ (Dlr.if' propertyState
(Dlr.blockSimple [
- (Dlr.assign propertyState
-
+ (Dlr.assign propertyState
+
#if NET2
(Dlr.call (Dlr.castT<System.Collections.IEnumerator> propertyEnumerator) "MoveNext" []))
#else
@@ -150,14 +150,14 @@ module internal ControlFlow =
(Dlr.ifElse
(Dlr.eq indexLength (Dlr.uint0))
(Dlr.break' break')
- (Binary.assign ctx target
+ (Binary.assign ctx target
(Ast.DlrExpr (Dlr.castT<double> indexCurrent)))))
(body |> ctx.Compile)
(Dlr.labelExprVoid continue')
- (Dlr.if'
+ (Dlr.if'
(Dlr.eq propertyState Dlr.false')
(Dlr.blockSimple [
(Dlr.assign indexLength (Dlr.sub indexLength Dlr.uint1))
@@ -176,7 +176,7 @@ module internal ControlFlow =
| (available, used)::groups ->
match available |> Map.tryFind name with
| Some(id, label) when FSharp.Utils.refEq label compareLabel ->
-
+
match locateLabelGroup name groups compareLabel with
| None ->
used := !used |> Map.add id label
@@ -198,39 +198,39 @@ module internal ControlFlow =
/// 12.7 continue
let continue' (ctx:Ctx) (name:string option) =
match name with
- | None ->
+ | None ->
match ctx.Labels.Continue with
- | Some label ->
+ | Some label ->
let groups = ctx.Labels.ContinueCompilers
- compileJump<FinallyContinueJump> groups "~default" label
+ compileJump<FinallyContinueJump> groups "~default" label
| _ -> Error.CompileError.Raise(Error.missingContinue)
| Some name ->
match ctx.Labels.ContinueLabels.TryFind name with
- | Some label ->
+ | Some label ->
let groups = ctx.Labels.ContinueCompilers
- compileJump<FinallyContinueJump> groups name label
+ compileJump<FinallyContinueJump> groups name label
| _ -> Error.CompileError.Raise(Error.missingLabel name)
-
+
//----------------------------------------------------------------------------
// 12.8 break
let break' (ctx:Ctx) (name:string option) =
match name with
- | None ->
+ | None ->
match ctx.Labels.Break with
- | Some label ->
- let groups = ctx.Labels.BreakCompilers
- compileJump<FinallyBreakJump> groups "~default" label
+ | Some label ->
+ let groups = ctx.Labels.BreakCompilers
+ compileJump<FinallyBreakJump> groups "~default" label
| _ -> Error.CompileError.Raise(Error.missingBreak)
| Some name ->
match ctx.Labels.BreakLabels.TryFind name with
- | Some label ->
- let groups = ctx.Labels.BreakCompilers
- compileJump<FinallyBreakJump> groups name label
+ | Some label ->
+ let groups = ctx.Labels.BreakCompilers
+ compileJump<FinallyBreakJump> groups name label
| _ -> Error.CompileError.Raise(Error.missingLabel name)
@@ -242,7 +242,7 @@ module internal ControlFlow =
let valueVar = Dlr.paramT<BV> "~value"
let breakLabel = Dlr.labelBreak()
-
+
let labels = ctx.Labels |> Labels.setDefaultBreak breakLabel
let ctx = {ctx with Labels = labels}
@@ -255,13 +255,13 @@ module internal ControlFlow =
| Ast.Cases.Case(value, body) ->
let value = ctx.Compile value
let label = Dlr.labelVoid (sprintf "case-%i" i)
- let test =
- (Dlr.if'
- (Operators.same(valueVar, Utils.box value))
+ let test =
+ (Dlr.if'
+ (DlrOps.same(valueVar, Utils.box value))
(Dlr.jump label)
)
- let body =
+ let body =
Dlr.block [] [
Dlr.labelExprVoid label
ctx $ Context.compile body
@@ -299,7 +299,7 @@ module internal ControlFlow =
Dlr.block [] [for test, _ in compiledCases -> test]
// Default jump, which could be either directly to
- // break in the case of no default-case or to
+ // break in the case of no default-case or to
// the default case body
!defaultJump
@@ -321,4 +321,4 @@ module internal ControlFlow =
let labels = ctx.Labels |> Labels.addNamedBreak label target
let ctx = {ctx with Labels = labels}
- Dlr.block [] [ctx $ compile tree; Dlr.labelExprVoid target]
+ Dlr.block [] [ctx $ compile tree; Dlr.labelExprVoid target]
View
164 Src/IronJS/Compiler.Operators.fs
@@ -8,17 +8,17 @@ open IronJS.Support.CustomOperators
open IronJS.Support.Aliases
module internal Unary =
-
+
//----------------------------------------------------------------------------
// 11.3
let postIncDec (ctx:Ctx) (ast:Ast.Tree) op =
let expr = ctx.Compile ast
- let incrementExpr =
+ let incrementExpr =
ctx.Compile(
- Ast.Assign(ast,
- Ast.Binary(op,
- Ast.Convert(TypeTags.Number, ast),
+ Ast.Assign(ast,
+ Ast.Binary(op,
+ Ast.Convert(TypeTags.Number, ast),
Ast.Number 1.0)))
Dlr.blockTmp expr.Type (fun tmp ->
@@ -34,19 +34,19 @@ module internal Unary =
//----------------------------------------------------------------------------
// 11.3.2
let postDecrement ctx ast = postIncDec ctx ast Ast.BinaryOp.Sub
-
+
//----------------------------------------------------------------------------
// 11.4.1 delete
let deleteIndex (ctx:Ctx) object' index =
(Utils.ensureObject ctx object'
(fun x -> Dlr.call x "Delete" [index])
(fun x -> Dlr.false'))
-
+
let deleteProperty (ctx:Ctx) object' name =
(Utils.ensureObject ctx object'
(fun x -> Dlr.call x "Delete" [!!!name])
(fun x -> Dlr.false'))
-
+
let deleteIdentifier (ctx:Ctx) name =
if ctx.DynamicLookup then
let args = [ctx.Parameters.DynamicScope :> Dlr.Expr; ctx.Globals; Dlr.const' name]
@@ -63,7 +63,7 @@ module internal Unary =
let delete (ctx:Ctx) tree =
match tree with
- | Ast.Identifier name ->
+ | Ast.Identifier name ->
deleteIdentifier ctx name
| Ast.Index(object', index) ->
@@ -84,67 +84,67 @@ module internal Unary =
// 11.4.2
let void' (ctx:Ctx) ast =
Dlr.blockSimple [ctx.Compile ast; Utils.Constants.undefined]
-
+
//----------------------------------------------------------------------------
// 11.4.3
- let typeOf (ctx:Ctx) (ast:Ast.Tree) =
+ let typeOf (ctx:Ctx) (ast:Ast.Tree) =
match ast with
| Ast.Identifier name ->
let expr =
- if name |> Identifier.isGlobal ctx then
-
- // We have to use the proper
+ if name |> Identifier.isGlobal ctx then
+
+ // We have to use the proper
// .Get method of the global object
// here to make sure we don't throw
// a reference exception when a non
// defined variable is accessed
Object.Property.get !!!name ctx.Globals
- else
+ else
ast |> ctx.Compile
- expr |> Utils.box |> Operators.typeOf
-
+ expr |> Utils.box |> DlrOps.typeOf
+
| _ ->
- ast |> ctx.Compile |> Utils.box |> Operators.typeOf
-
+ ast |> ctx.Compile |> Utils.box |> DlrOps.typeOf
+
//----------------------------------------------------------------------------
// 11.4.4, 11.4.5
let preIncDec (ctx:Ctx) ast op =
- let incrementExpr =
+ let incrementExpr =
ctx.Compile(
- Ast.Assign(ast,
- Ast.Binary(op,
- Ast.Convert(TypeTags.Number, ast),
+ Ast.Assign(ast,
+ Ast.Binary(op,
+ Ast.Convert(TypeTags.Number, ast),
Ast.Number 1.0)))
Dlr.blockSimple [incrementExpr; ctx.Compile ast]
-
+
let increment ctx ast = preIncDec ctx ast Ast.BinaryOp.Add
let decrement ctx ast = preIncDec ctx ast Ast.BinaryOp.Sub
-
+
//----------------------------------------------------------------------------
// 11.4.6
let plus (ctx:Ctx) ast =
- Dlr.callStaticT<Operators> "plus" [ctx.Compile ast |> Utils.box]
+ DlrOps.plus (ctx.Compile ast |> Utils.box)
//----------------------------------------------------------------------------
// 11.4.7
let minus (ctx:Ctx) ast =
- Dlr.callStaticT<Operators> "minus" [ctx.Compile ast |> Utils.box]
-
+ DlrOps.minus (ctx.Compile ast |> Utils.box)
+
//----------------------------------------------------------------------------
// 11.4.8
let complement (ctx:Ctx) ast =
- Dlr.callStaticT<Operators> "bitCmpl" [ctx.Compile ast |> Utils.box]
+ DlrOps.bitCmpl (ctx.Compile ast |> Utils.box)
//----------------------------------------------------------------------------
// 11.4.9
let not (ctx:Ctx) ast =
- Dlr.callStaticT<Operators> "not" [ctx.Compile ast |> Utils.box]
-
+ DlrOps.not (ctx.Compile ast |> Utils.box)
+
//----------------------------------------------------------------------------
let convert (ctx:Ctx) (tag:uint32) (ast:Ast.Tree) =
match tag with
@@ -153,7 +153,7 @@ module internal Unary =
| _ -> failwith "Que?"
- ///
+ ///
let compile ctx op ast =
match op with
| Ast.UnaryOp.Delete -> delete ctx ast
@@ -170,8 +170,8 @@ module internal Unary =
| _ -> failwithf "Invalid unary op %A" op
///
-module internal Binary =
-
+module internal Binary =
+
///
let private toNumber (expr:Dlr.Expr) =
Utils.Convert.toNumber expr
@@ -184,13 +184,13 @@ module internal Binary =
let private toInt32 (expr:Dlr.Expr) =
expr |> toUInt32 |> Dlr.castT<int32>
- /// This method is intended for internal use only
+ /// This method is intended for internal use only
/// and uses mutable lists for performance reasons
let private getStaticExpression (vars:Dlr.ParameterList) (body:Dlr.ExprList) expr =
- if expr |> Dlr.isStatic then
+ if expr |> Dlr.isStatic then
expr
- else
+ else
let temp = Dlr.param "~tmp" expr.Type
vars.Add(temp)
body.Add(temp .= expr)
@@ -209,11 +209,11 @@ module internal Binary =
Dlr.block vars body
///
- let private bitOperator op l r : Dlr.Expr =
+ let private bitOperator op l r : Dlr.Expr =
op (toInt32 l) (toInt32 r) |> Dlr.castT<double>
///
- let private bitShiftOperator op convert l r : Dlr.Expr =
+ let private bitShiftOperator op convert l r : Dlr.Expr =
let r = ((r |> toUInt32) .& (!!!0x1Fu)) |> Dlr.castT<int>
op (convert l) r |> Dlr.castT<double>
@@ -221,7 +221,7 @@ module internal Binary =
let private addOperator l r =
let vars = new Dlr.ParameterList()
let body = new Dlr.ExprList()
-
+
let l = l |> getStaticExpression vars body
let r = r |> getStaticExpression vars body
@@ -229,25 +229,25 @@ module internal Binary =
match TypeTag.OfType(l.Type), TypeTag.OfType(r.Type) with
| TypeTags.Number, TypeTags.Number -> Dlr.add l r
| TypeTags.Number, TypeTags.Box ->
- Dlr.ternary (Utils.Box.isNumber r)
+ Dlr.ternary (Utils.Box.isNumber r)
(Dlr.add l (Utils.Box.unboxNumber r) |> Utils.box)
- (Operators.add (Utils.box l, Utils.box r))
+ (DlrOps.add (Utils.box l, Utils.box r))
| TypeTags.Box, TypeTags.Number ->
- Dlr.ternary (Utils.Box.isNumber l)
+ Dlr.ternary (Utils.Box.isNumber l)
(Dlr.add (Utils.Box.unboxNumber l) r |> Utils.box)
- (Operators.add(Utils.box l, Utils.box r))
+ (DlrOps.add(Utils.box l, Utils.box r))
| TypeTags.Box, TypeTags.Box ->
- Dlr.ternary (Utils.Box.isNumber l .&& Utils.Box.isNumber r)
+ Dlr.ternary (Utils.Box.isNumber l .&& Utils.Box.isNumber r)
(Dlr.add (Utils.Box.unboxNumber l) (Utils.Box.unboxNumber r) |> Utils.box)
- (Operators.add(l, r))
+ (DlrOps.add(l, r))
| _ ->
- Operators.add(Utils.box l, Utils.box r)
+ DlrOps.add(Utils.box l, Utils.box r)
)
- if vars.Count = 0 && body.Count = 1
+ if vars.Count = 0 && body.Count = 1
then body.[0]
else Dlr.block vars body
@@ -255,27 +255,27 @@ module internal Binary =
let private relationalOperator op fallback l r =
let vars = new Dlr.ParameterList()
let body = new Dlr.ExprList()
-
+
let l = l |> getStaticExpression vars body
let r = r |> getStaticExpression vars body
body.Add (
match TypeTag.OfType(l.Type), TypeTag.OfType(r.Type) with
- | TypeTags.Number, TypeTags.Number ->
+ | TypeTags.Number, TypeTags.Number ->
op l r
| TypeTags.Number, TypeTags.Box ->
- Dlr.ternary (Utils.Box.isNumber r)
+ Dlr.ternary (Utils.Box.isNumber r)
(op l (Utils.Box.unboxNumber r))
(fallback (Utils.box l, Utils.box r))
| TypeTags.Box, TypeTags.Number ->
- Dlr.ternary (Utils.Box.isNumber l)
+ Dlr.ternary (Utils.Box.isNumber l)
(op (Utils.Box.unboxNumber l) r)
(fallback (Utils.box l, Utils.box r))
| TypeTags.Box, TypeTags.Box ->
- Dlr.ternary (Utils.Box.isNumber l .&& Utils.Box.isNumber r)
+ Dlr.ternary (Utils.Box.isNumber l .&& Utils.Box.isNumber r)
(op (Utils.Box.unboxNumber l) (Utils.Box.unboxNumber r))
(fallback (l, r))
@@ -283,7 +283,7 @@ module internal Binary =
fallback(Utils.box l, Utils.box r)
)
- if vars.Count = 0 && body.Count = 1
+ if vars.Count = 0 && body.Count = 1
then body.[0]
else Dlr.block vars body
@@ -291,14 +291,14 @@ module internal Binary =
let private equalityOperator op fallback constResult l r =
let vars = new Dlr.ParameterList()
let body = new Dlr.ExprList()
-
+
let l = l |> getStaticExpression vars body
let r = r |> getStaticExpression vars body
body.Add (
match TypeTag.OfType(l.Type), TypeTag.OfType(r.Type) with
| TypeTags.Box, TypeTags.Box ->
- Dlr.ternary (Utils.Box.isNumber l .&& Utils.Box.isNumber r)
+ Dlr.ternary (Utils.Box.isNumber l .&& Utils.Box.isNumber r)
(op (Utils.Box.unboxNumber l) (Utils.Box.unboxNumber r))
(fallback (l, r))
@@ -308,12 +308,12 @@ module internal Binary =
op l r
| TypeTags.Number, TypeTags.Box ->
- Dlr.ternary (Utils.Box.isNumber r)
+ Dlr.ternary (Utils.Box.isNumber r)
(op l (Utils.Box.unboxNumber r))
(fallback(Utils.box l, Utils.box r))
| TypeTags.Box, TypeTags.Number ->
- Dlr.ternary (Utils.Box.isNumber l)
+ Dlr.ternary (Utils.Box.isNumber l)
(op (Utils.Box.unboxNumber l) r)
(fallback(Utils.box l, Utils.box r))
@@ -321,7 +321,7 @@ module internal Binary =
fallback(Utils.box l, Utils.box r)
)
- if vars.Count = 0 && body.Count = 1
+ if vars.Count = 0 && body.Count = 1
then body.[0]
else Dlr.block vars body
@@ -342,45 +342,45 @@ module internal Binary =
| Ast.BinaryOp.BitShiftRight -> bitShiftOperator Dlr.rhs toInt32 l r
| Ast.BinaryOp.BitUShiftRight -> bitShiftOperator Dlr.rhs toUInt32 l r
- | Ast.BinaryOp.Eq -> equalityOperator Dlr.eq Operators.eq None l r
- | Ast.BinaryOp.NotEq -> equalityOperator Dlr.notEq Operators.notEq None l r
- | Ast.BinaryOp.Same -> equalityOperator Dlr.eq Operators.same (Some true) l r
- | Ast.BinaryOp.NotSame -> equalityOperator Dlr.notEq Operators.notSame (Some true) l r
+ | Ast.BinaryOp.Eq -> equalityOperator Dlr.eq DlrOps.eq None l r
+ | Ast.BinaryOp.NotEq -> equalityOperator Dlr.notEq DlrOps.notEq None l r
+ | Ast.BinaryOp.Same -> equalityOperator Dlr.eq DlrOps.same (Some true) l r
+ | Ast.BinaryOp.NotSame -> equalityOperator Dlr.notEq DlrOps.notSame (Some true) l r
- | Ast.BinaryOp.Lt -> relationalOperator Dlr.lt Operators.lt l r
- | Ast.BinaryOp.LtEq -> relationalOperator Dlr.ltEq Operators.ltEq l r
- | Ast.BinaryOp.Gt -> relationalOperator Dlr.gt Operators.gt l r
- | Ast.BinaryOp.GtEq -> relationalOperator Dlr.gtEq Operators.gtEq l r
+ | Ast.BinaryOp.Lt -> relationalOperator Dlr.lt DlrOps.lt l r
+ | Ast.BinaryOp.LtEq -> relationalOperator Dlr.ltEq DlrOps.ltEq l r
+ | Ast.BinaryOp.Gt -> relationalOperator Dlr.gt DlrOps.gt l r
+ | Ast.BinaryOp.GtEq -> relationalOperator Dlr.gtEq DlrOps.gtEq l r
- | Ast.BinaryOp.In -> Operators.in'(ctx.Env, l |> Utils.box, r |> Utils.box)
- | Ast.BinaryOp.InstanceOf -> Operators.instanceOf(ctx.Env, l |> Utils.box, r |> Utils.box)
+ | Ast.BinaryOp.In -> DlrOps.in'(ctx.Env, l |> Utils.box, r |> Utils.box)
+ | Ast.BinaryOp.InstanceOf -> DlrOps.instanceOf(ctx.Env, l |> Utils.box, r |> Utils.box)
| _ -> failwithf "Invalid BinaryOp %A" op
-
- /// Implements compilation for:
+
+ /// Implements compilation for:
let compile (ctx:Ctx) op left right =
match op with
- | Ast.BinaryOp.Or ->
+ | Ast.BinaryOp.Or ->
let l = left |> ctx.Compile
let l_tmp = Dlr.param "~left" l.Type
Dlr.block [l_tmp] [
l_tmp .= l
- (Dlr.ternary
+ (Dlr.ternary
(Dlr.callStaticT<TC> "ToBoolean" [l_tmp])
(Utils.box l_tmp)
(Utils.box (right |> ctx.Compile))
)
]
- | Ast.BinaryOp.And ->
+ | Ast.BinaryOp.And ->
let l = left |> ctx.Compile
let l_tmp = Dlr.param "~left" l.Type
Dlr.block [l_tmp] [
l_tmp .= l
- (Dlr.ternary
+ (Dlr.ternary
(Dlr.callStaticT<TC> "ToBoolean" [l_tmp])
(Utils.box (right |> ctx.Compile))
(Utils.box l_tmp)
@@ -398,15 +398,15 @@ module internal Binary =
match ltree with
//Variable assignment: foo = 1;
- | Ast.Identifier(name) ->
+ | Ast.Identifier(name) ->
Identifier.setValue ctx name value
//Property assignment: foo.bar = 1;
- | Ast.Property(object', name) ->
+ | Ast.Property(object', name) ->
Object.putMember ctx (object' |> ctx.Compile) name value
//Index assignemnt: foo[0] = "bar";
- | Ast.Index(object', index) ->
+ | Ast.Index(object', index) ->
Utils.tempBlock value (fun value ->
let object' = object' |> ctx.Compile
let index = Utils.compileIndex ctx index
@@ -416,8 +416,8 @@ module internal Binary =
)
| _ -> failwithf "Failed to compile assign for: %A" ltree
-
- /// Implements compilation for
+
+ /// Implements compilation for
let compoundAssign (ctx:Ctx) op ltree rtree =
match ltree with
| Ast.Index(obj, idx) ->
@@ -430,6 +430,6 @@ module internal Binary =
tmp .= idx
assign ctx ltree (Ast.Binary(op, ltree, rtree))
]
-
+
| _ ->
- assign ctx ltree (Ast.Binary(op, ltree, rtree))
+ assign ctx ltree (Ast.Binary(op, ltree, rtree))
View
327 Src/IronJS/Operators.fs
@@ -5,338 +5,21 @@ open IronJS
open IronJS.Runtime
open IronJS.Support.Aliases
-(*
-// This file implements all (non-assign) binary and unary operators
-//
-// DONE:
-// 11.4.1 The delete Operator
-// 11.4.2 The void Operator
-// 11.4.3 The typeof Operator
-// 11.4.6 Unary + Operator
-// 11.4.7 Unary - Operator
-// 11.4.8 Bitwise NOT Operator ( ~ )
-// 11.4.9 Logical NOT Operator ( ! )
-// 11.5.1 Applying the * Operator
-// 11.5.2 Applying the / Operator
-// 11.5.3 Applying the % Operator
-// 11.6.1 The Addition operator ( + )
-// 11.6.2 The Subtraction Operator ( - )
-// 11.7.1 The Left Shift Operator ( << )
-// 11.7.2 The Signed Right Shift Operator ( >> )
-// 11.7.3 The Unsigned Right Shift Operator ( >>> )
-// 11.8.1 The Less-than Operator ( < )
-// 11.8.2 The Greater-than Operator ( > )
-// 11.8.3 The Less-than-or-equal Operator ( <= )
-// 11.8.4 The Greater-than-or-equal Operator ( >= )
-// 11.8.6 The instanceof operator
-// 11.8.7 The in operator
-// 11.9.1 The Equals Operator ( == )
-// 11.9.2 The Does-not-equals Operator ( != )
-// 11.9.4 The Strict Equals Operator ( === )
-// 11.9.5 The Strict Does-not-equal Operator ( !== )
-// 11.10 Binary Bitwise Operators
-// 11.11 Binary Logical Operators
-// 11.12 Conditional Operator ( ?: )
-*)
-
-//------------------------------------------------------------------------------
-// Operators
-type Operators =
-
- //----------------------------------------------------------------------------
- // Unary
- //----------------------------------------------------------------------------
-
- //----------------------------------------------------------------------------
- // typeof
- static member typeOf (o:BV) =
- if o.IsNumber then "number"
- elif o.IsNull then "object"
- else TypeTags.GetName(o.Tag)
+type DlrOps =
static member typeOf expr = Dlr.callStaticT<Operators> "typeOf" [expr]
-
- //----------------------------------------------------------------------------
- // !
static member not (o) = Dlr.callStaticT<Operators> "not" [o]
- static member not (o:BV) =
- not (TC.ToBoolean o)
-
- //----------------------------------------------------------------------------
- // ~
static member bitCmpl (o) = Dlr.callStaticT<Operators> "bitCmpl" [o]
- static member bitCmpl (o:BV) =
- let o = TC.ToNumber o
- let o = TC.ToInt32 o
- ~~~ o |> double
-
- //----------------------------------------------------------------------------
- // + (unary)
- static member plus (l, r) = Dlr.callStaticT<Operators> "plus" [l; r]
- static member plus (o:BV) =
- o |> TC.ToNumber |> BV.Box
-
- //----------------------------------------------------------------------------
- // - (unary)
- static member minus (l, r) = Dlr.callStaticT<Operators> "minus" [l; r]
- static member minus (o:BV) =
- BV.Box ((TC.ToNumber o) * -1.0)
-
- //----------------------------------------------------------------------------
- // Binary
- //----------------------------------------------------------------------------
-
- //----------------------------------------------------------------------------
- // in
- static member in' (env, l,r) = Dlr.callStaticT<Operators> "in'" [env; l; r]
- static member in' (env:Env, l:BV, r:BV) =
- if not r.IsObject then
- env.RaiseTypeError("Right operand is not a object")
-
- let mutable index = 0u
- if TC.TryToIndex(l, &index) then
- r.Object.Has(index)
-
- else
- let name = TC.ToString(l)
- r.Object.Has(name)
-
- //----------------------------------------------------------------------------
- // instanceof
- static member instanceOf (env, l,r) =
- Dlr.callStaticT<Operators> "instanceOf" [env; l; r]
-
- static member instanceOf(env:Env, l:BV, r:BV) =
- if r.IsFunction |> not then
- env.RaiseTypeError("Right operand is not a function")
-
- if not l.IsObject
- then false
- else r.Func.HasInstance(l.Object)
-
- //----------------------------------------------------------------------------
- // <
+ static member plus (o) = Dlr.callStaticT<Operators> "plus" [o]
+ static member minus (o) = Dlr.callStaticT<Operators> "minus" [o]
+ static member in' (env, l,r) = Dlr.callStaticT<Operators> "in" [env; l; r]
+ static member instanceOf (env, l,r) = Dlr.callStaticT<Operators> "instanceOf" [env; l; r]
static member lt (l, r) = Dlr.callStaticT<Operators> "lt" [l; r]
- static member lt (l:BV, r:BV) =
- match l.Tag, r.Tag with
- | TypeTags.String, TypeTags.SuffixString
- | TypeTags.SuffixString, TypeTags.String ->
- l.Clr.ToString() < r.Clr.ToString()
-
- | _ ->
- if l.IsNumber && r.IsNumber
- then l.Number < r.Number
- elif l.Tag = TypeTags.String && r.Tag = TypeTags.String
- then l.String < r.String
- else
- let l' = TC.ToPrimitive(l, DefaultValueHint.Number)
- let r' = TC.ToPrimitive(r, DefaultValueHint.Number)
- if l'.IsString && r'.IsString
- then l'.String < r'.String
- else TC.ToNumber l' < TC.ToNumber r'
-
- //----------------------------------------------------------------------------
- // <=
static member ltEq (l, r) = Dlr.callStaticT<Operators> "ltEq" [l; r]
- static member ltEq (l:BV, r:BV) =
- match l.Tag, r.Tag with
- | TypeTags.String, TypeTags.SuffixString
- | TypeTags.SuffixString, TypeTags.String ->
- l.Clr.ToString() <= r.Clr.ToString()
-
- | _ ->
- if l.IsNumber && r.IsNumber
- then l.Number <= r.Number
- elif l.Tag = TypeTags.String && r.Tag = TypeTags.String
- then l.String <= r.String
- else
- let r' = TC.ToPrimitive(r, DefaultValueHint.Number)
- let l' = TC.ToPrimitive(l, DefaultValueHint.Number)
- if l'.IsString && r'.IsString
- then l'.String <= r'.String
- else TC.ToNumber l' <= TC.ToNumber r'
-
- //----------------------------------------------------------------------------
- // >
static member gt (l, r) = Dlr.callStaticT<Operators> "gt" [l; r]
- static member gt (l:BV, r:BV) =
- match l.Tag, r.Tag with
- | TypeTags.String, TypeTags.SuffixString
- | TypeTags.SuffixString, TypeTags.String ->
- l.Clr.ToString() > r.Clr.ToString()
-
- | _ ->
- if l.IsNumber && r.IsNumber
- then l.Number > r.Number
- elif l.Tag = TypeTags.String && r.Tag = TypeTags.String
- then l.String > r.String
- else
- let r' = TC.ToPrimitive(r, DefaultValueHint.Number)
- let l' = TC.ToPrimitive(l, DefaultValueHint.Number)
- if l'.IsString && r'.IsString
- then l'.String > r'.String
- else TC.ToNumber l' > TC.ToNumber r'
-
- //----------------------------------------------------------------------------
- // >=
static member gtEq (l, r) = Dlr.callStaticT<Operators> "gtEq" [l; r]
- static member gtEq (l:BV, r:BV) =
- match l.Tag, r.Tag with
- | TypeTags.String, TypeTags.SuffixString
- | TypeTags.SuffixString, TypeTags.String ->
- l.Clr.ToString() >= r.Clr.ToString()
-
- | _ ->
- if l.IsNumber && r.IsNumber
- then l.Number >= r.Number
- elif l.Tag = TypeTags.String && r.Tag = TypeTags.String
- then l.String >= r.String
- else
- let l' = TC.ToPrimitive(l, DefaultValueHint.Number)
- let r' = TC.ToPrimitive(r, DefaultValueHint.Number)
- if l'.IsString && r'.IsString
- then l'.String >= r'.String
- else TC.ToNumber l' >= TC.ToNumber r'
-
- //----------------------------------------------------------------------------
- // ==
static member eq (l, r) = Dlr.callStaticT<Operators> "eq" [l; r]
- static member eq (l:BV, r:BV) =
- if l.IsNumber && r.IsNumber then
- l.Number = r.Number
-
- elif l.Tag = r.Tag then
- match l.Tag with
- | TypeTags.Undefined -> true
- | TypeTags.String -> l.String = r.String
- | TypeTags.SuffixString -> l.Clr.ToString() = r.Clr.ToString()
- | TypeTags.Bool -> l.Bool = r.Bool
- | TypeTags.Clr
- | TypeTags.Function
- | TypeTags.Object -> Object.ReferenceEquals(l.Clr, r.Clr)
- | _ -> false
-
- else
- match l.Tag, r.Tag with
- | TypeTags.String, TypeTags.SuffixString
- | TypeTags.SuffixString, TypeTags.String ->
- l.Clr.ToString() = r.Clr.ToString()
-
- | _ ->
- if l.Tag = TypeTags.Clr
- && l.Clr = null
- && r.Tag = TypeTags.Undefined then true
-
- elif r.Tag = TypeTags.Clr
- && r.Clr = null
- && l.Tag = TypeTags.Undefined then true
-
- elif l.IsNumber && r.IsString then
- l.Number = TC.ToNumber r.String
-
- elif l.IsString && r.IsNumber then
- TC.ToNumber l.String = r.Number
-
- elif l.Tag = TypeTags.Bool then
- let mutable l = BV.Box(TC.ToNumber l)
- Operators.eq(l, r)
-
- elif r.Tag = TypeTags.Bool then
- let mutable r = BV.Box(TC.ToNumber r)
- Operators.eq(l, r)
-
- elif r.Tag >= TypeTags.Object then
- match l.Tag with
- | TypeTags.SuffixString
- | TypeTags.String ->
- let r = TC.ToPrimitive(r.Object, DefaultValueHint.None)
- Operators.eq(l, r)
-
- | _ ->
- if l.IsNumber then
- let r = TC.ToPrimitive(r.Object, DefaultValueHint.None)
- Operators.eq(l, r)
- else
- false
-
- elif l.Tag >= TypeTags.Object then
- match r.Tag with
- | TypeTags.SuffixString
- | TypeTags.String ->
- let l = TC.ToPrimitive(l.Object, DefaultValueHint.None)
- Operators.eq(l, r)
-
- | _ ->
- if r.IsNumber then
- let l = TC.ToPrimitive(l.Object, DefaultValueHint.None)
- Operators.eq(l, r)
- else
- false
-
- else
- false
-
- //----------------------------------------------------------------------------
- // !=
static member notEq (l, r) = Dlr.callStaticT<Operators> "notEq" [l; r]
- static member notEq (l:BV, r:BV) = not (Operators.eq(l, r))
-
- //----------------------------------------------------------------------------
- // ===
static member same (l, r) = Dlr.callStaticT<Operators> "same" [l; r]
- static member same (l:BV, r:BV) =
- if l.IsNumber && r.IsNumber then
- l.Number = r.Number
-
- elif l.Tag = r.Tag then
- match l.Tag with
- | TypeTags.Undefined -> true
- | TypeTags.String -> l.String = r.String
- | TypeTags.Bool -> l.Bool = r.Bool
- | TypeTags.Clr
- | TypeTags.Function
- | TypeTags.Object -> Object.ReferenceEquals(l.Clr, r.Clr)
- | TypeTags.SuffixString -> l.Clr.ToString() = r.Clr.ToString()
- | _ -> false
-
- else
- match l.Tag, r.Tag with
- | TypeTags.SuffixString, TypeTags.String -> l.Clr.ToString() = r.String
- | TypeTags.String, TypeTags.SuffixString -> l.String = r.Clr.ToString()
- | _ -> false
-
- //----------------------------------------------------------------------------
- // !==
static member notSame (l, r) = Dlr.callStaticT<Operators> "notSame" [l; r]
- static member notSame (l:BV, r:BV) =
- Operators.same(l, r) |> not
-
- //----------------------------------------------------------------------------
- // +
static member add (l, r) = Dlr.callStaticT<Operators> "add" [l; r]
- static member add (l:BV, r:BV) =
- let rec fallback (l:BV) (r:BV) =
- let l = TC.ToPrimitive(l)
- let r = TC.ToPrimitive(r)
-
- match l.Tag, r.Tag with
- | TypeTags.SuffixString, _ ->
- BV.Box(SuffixString.Concat(l.SuffixString, TC.ToString(r)))
-
- | TypeTags.String, _
- | _, TypeTags.String ->
- BV.Box(SuffixString.Concat(TC.ToString(l), TC.ToString(r)))
-
- | _ ->
- BV.Box(TC.ToNumber(l) + TC.ToNumber(r))
-
- match l.Tag, r.Tag with
- | TypeTags.SuffixString, _ ->
- BV.Box(SuffixString.Concat(l.SuffixString, TC.ToString(TC.ToPrimitive(r))))
-
- | TypeTags.String, _
- | _, TypeTags.String ->
- BV.Box(SuffixString.Concat(TC.ToString(TC.ToPrimitive(l)), TC.ToString(TC.ToPrimitive(r))))
-
- | _ ->
- fallback l r
Please sign in to comment.
Something went wrong with that request. Please try again.