Skip to content
Browse files

Solve problem wiht jQuery style callables and several other fixes to …

…the resolution of callable types
  • Loading branch information...
1 parent cea3828 commit 986b4e4f34934bd381d7bf5e477e08effdac538c @drslump committed Oct 7, 2012
View
250 src/Boo.js
@@ -4,7 +4,9 @@
/*jshint indent:4 lastsemic:false curly:false */
-var Boo = {};
+var Boo = {
+ BOO_RUNTIME_VERSION: '0.0.1'
+};
// Used as a unique indentifier when we want to stop iterating a generator
Boo.STOP = { retval: undefined };
@@ -19,9 +21,7 @@ Boo.Types = {
'int': 'int',
'uint': 'uint',
'double': 'double',
- 'callable': 'callable',
- // HACK: Javascript global objects
- 'Math': Math
+ 'callable': 'callable'
};
// Note: We don't use the native forEach method since this is custom tailored
@@ -216,10 +216,99 @@ Boo.slice = function (value, begin, end, step) {
return (typeof value === 'string') ? result.join('') : result;
};
+
+// Casts a value to the given type, raising an error if it's not possible
+Boo.cast = function (value, type) {
+ // TODO: This is an absolute hack!!!
+ var t = type, tof = typeof(value);
+ if (t === Boo.Types.int || t === Boo.Types.uint || t === Boo.Types.double) t = 'number';
+
+ if (tof === t)
+ return value;
+ else if (tof !== 'undefined' && t === 'object')
+ return value;
+ else if ((tof === 'undefined' || value === null) && t === 'number')
+ return 0;
+ else if ((tof === 'undefined' || value === null) && t === 'string')
+ return '';
+ else
+ throw new Error('Unable to cast from ' + tof + ' to ' + type);
+};
+
+// Casts a value to the given type, resulting in a null if it's not possible
+Boo.trycast = function (value, type) {
+ try {
+ return Boo.Lang.cast(value, type);
+ } catch (e) {
+ return null;
+ }
+};
+
+// Makes sure a value is enumerable
+Boo.enumerable = function (value) {
+ if (typeof value === 'string' || typeof value === 'object' && value.length === +value.length) {
+ return value;
+ }
+
+ throw new Error('Unable to cast to enumerable the value "' + value + '"');
+};
+
+
+////////// Operators /////////////////////////////////////////////////
+
+// Compares two values for equality
+Boo.op_Equality = function (lhs, rhs) {
+ return lhs == rhs;
+};
+
+// Perform the modulus operation on two operands
+Boo.op_Modulus = function (lhs, rhs) {
+ // Check if we should format a string
+ if (typeof lhs === 'string' && typeof rhs === 'object') {
+ return lhs.replace(/\{(\d+)\}/g, function (m, capt) {
+ return rhs[capt];
+ });
+ } else {
+ return lhs % rhs;
+ }
+};
+
+// Perform an addition operation on two operands
+Boo.op_Addition = function (lhs, rhs) {
+ return lhs + rhs;
+};
+
+// Perform a multiply operation on two operands
+Boo.op_Multiply = function (lhs, rhs) {
+ if (typeof lhs === 'number') {
+ var _ = lhs;
+ lhs = rhs;
+ rhs = _;
+ }
+ if (typeof lhs === 'string' && typeof rhs === 'number')
+ return Boo.Lang.String.op_Multiply(lhs, rhs);
+ if (typeof lhs === 'object' && lhs.length === +lhs.length)
+ return Boo.Lang.Array.op_Multiply(rhs, lhs);
+
+ return lhs * rhs;
+};
+
+// Perform a regexp match
+Boo.op_Match = function (lhs, rhs) {
+ if (typeof rhs === 'string') rhs = new RegExp(rhs);
+ return rhs.test(lhs);
+};
+Boo.op_NotMatch = function (lhs, rhs) {
+ return !Boo.op_Match(lhs, rhs);
+};
+
+
// Runtime support for String type
Boo.String = {
op_Modulus: function (lhs, rhs) {
- return Boo.Lang.formatter(lhs, rhs);
+ return lhs.replace(/\{(\d+)\}/g, function (m, capt) {
+ return rhs[capt];
+ });
},
op_Multiply: function (lhs, rhs) {
var result = new Array(rhs);
@@ -266,154 +355,3 @@ Boo.Array = {
return result;
}
};
-
-// Runtime support library
-Boo.Lang = {
- // Casts a value to the given type, raising an error if it's not possible
- cast: function (value, type) {
- // TODO: This is an absolute hack!!!
- var t = type, tof = typeof(value);
- if (t === Boo.Types.int || t === Boo.Types.uint || t === Boo.Types.double) t = 'number';
-
- if (tof === t)
- return value;
- else if (tof !== 'undefined' && t === 'object')
- return value;
- else if ((tof === 'undefined' || value === null) && t === 'number')
- return 0;
- else if ((tof === 'undefined' || value === null) && t === 'string')
- return '';
- else
- throw new Error('Unable to cast from ' + tof + ' to ' + type);
- },
-
- // Casts a value to the given type, resulting in a null if it's not possible
- trycast: function (value, type) {
- try {
- return Boo.Lang.cast(value, type);
- } catch (e) {
- return null;
- }
- },
-
- // Makes sure a value is enumerable
- enumerable: function (value) {
- if (typeof value === 'string' || typeof value === 'object' && value.length === +value.length) {
- return value;
- }
-
- throw new Error('Unable to cast to enumerable the value "' + value + '"');
- },
-
-
- // Compares two values for equality
- op_Equality: function (lhs, rhs) {
- return lhs == rhs;
- },
-
- // Perform the modulus operation on two operands
- op_Modulus: function (lhs, rhs) {
- // Check if we should format a string
- if (typeof lhs === 'string' && typeof rhs === 'object') {
- return lhs.replace(/\{(\d+)\}/g, function (m, capt) {
- return rhs[capt];
- });
- } else {
- return lhs % rhs;
- }
- },
-
- // Perform an addition operation on two operands
- op_Addition: function (lhs, rhs) {
- return lhs + rhs;
- },
-
- // Perform a multiply operation on two operands
- op_Multiply: function (lhs, rhs) {
- if (typeof lhs === 'number') {
- var _ = lhs;
- lhs = rhs;
- rhs = _;
- }
- if (typeof lhs === 'string' && typeof rhs === 'number')
- return Boo.Lang.String.op_Multiply(lhs, rhs);
- if (typeof lhs === 'object' && lhs.length === +lhs.length)
- return Boo.Lang.Array.op_Multiply(rhs, lhs);
-
- return lhs * rhs;
- },
-
- // Perform a regexp match
- op_Match: function (lhs, rhs) {
- if (typeof rhs === 'string') rhs = new RegExp(rhs);
- return rhs.test(lhs);
- },
- op_NotMatch: function (lhs, rhs) {
- return !Boo.Lang.op_Match(lhs, rhs);
- },
-
- // Formats an string based on the given params
- // By default it replaces tokens like 'Hello {0} from {1}'
- formatter: function (tpl, params) {
- return tpl.replace(/\{(\d+)\}/g, function (m, capt) {
- return params[capt];
- });
- },
-
- Proto: {
- op_Addition: function (lhs, rhs) {
- if (lhs === null || rhs === null)
- return null;
- if (typeof lhs === 'object' && 'op_Addition' in lhs)
- return lhs.op_Addition(lhs, rhs);
- // Check if we are handling an array
- if (typeof lhs === 'object' && lhs.length === +lhs.length)
- return Boo.Lang.Array.op_Addition(lhs, rhs);
-
- return lhs + rhs;
- },
- op_Subtraction: function (lhs, rhs) {
- if (lhs === null || rhs === null)
- return null;
- if (typeof lhs === 'object' && 'op_Subtraction' in lhs)
- return lhs.op_Subtraction(lhs, rhs);
- // Check for array
- if (typeof lhs === 'object' && lhs.length === +lhs.length)
- throw new Error('Substraction operator not supported on arrays');
- if (typeof lhs === 'string')
- throw new Error('Substraction operator not supported on strings');
-
- return lhs - rhs;
- },
- op_Multiply: function (lhs, rhs) {
- if (lhs === null || rhs === null)
- return null;
- if (typeof lhs === 'object' && 'op_Multiply' in lhs)
- return lhs.op_Multiply(lhs, rhs);
- if (typeof lhs === 'string')
- return Boo.Lang.String.op_Multiply(lhs, rhs);
- if (typeof lhs === 'object' && lhs.length === +lhs.length)
- return Boo.Lang.Array.op_Multiply(lhs, rhs);
-
- return lhs * rhs;
- },
- op_Division: function (lhs, rhs) {
- if (lhs === null || rhs === null)
- return null;
- if (typeof lhs === 'object' && 'op_Division' in lhs)
- return lhs.op_Division(lhs, rhs);
- // Check for array
- if (typeof lhs === 'object' && lhs.length === +lhs.length)
- throw new Error('Division operator not supported on arrays');
- if (typeof lhs === 'string')
- throw new Error('Division operator not supported on strings');
-
- return lhs - rhs;
- }
- }
-};
-
-// HACK: Alias the runtime helpers
-Boo.Types.RuntimeHelpers = Boo.Lang;
-
-
View
4 src/BooJs.Compiler.Test/TypeSystemFixtures.boo
@@ -25,6 +25,10 @@ class FixtureForTypesystem:
FixtureRunner.run('/Users/drslump/www/boojs/tests/fixtures/typesystem/int.boo')
[Test]
+ def test_jquery():
+ FixtureRunner.run('/Users/drslump/www/boojs/tests/fixtures/typesystem/jquery.boo')
+
+ [Test]
def test_method_overloading():
FixtureRunner.run('/Users/drslump/www/boojs/tests/fixtures/typesystem/method-overloading.boo')
View
1 src/BooJs.Compiler/BooJs.Compiler.booproj
@@ -100,6 +100,7 @@
<Compile Include="Steps\MethodOverloading.boo" />
<Compile Include="TypeSystem\ReflectionProvider.boo" />
<Compile Include="TypeSystem\Services.boo" />
+ <Compile Include="TypeSystem\RuntimeMethodCache.boo" />
</ItemGroup>
<ItemGroup>
<Folder Include="SourceMap\" />
View
3 src/BooJs.Compiler/BooJsCompiler.boo
@@ -4,8 +4,9 @@ import System
import Boo.Lang.Environments
import Boo.Lang.Compiler
-import Boo.Lang.Compiler.TypeSystem
import Boo.Lang.Compiler.Ast
+import Boo.Lang.Compiler.TypeSystem(TypeSystemServices)
+import Boo.Lang.Compiler.TypeSystem.Services(RuntimeMethodCache)
import BooJs.Compiler.TypeSystem as BooJsTypeSystem
View
2 src/BooJs.Compiler/Steps/IntroduceNamespaces.boo
@@ -3,6 +3,7 @@ namespace BooJs.Compiler.Steps
import Boo.Lang.Compiler.Steps
import Boo.Lang.Compiler.TypeSystem.Core
+
class IntroduceNamespaces(IntroduceGlobalNamespaces):
override def Run():
@@ -14,3 +15,4 @@ class IntroduceNamespaces(IntroduceGlobalNamespaces):
SafeGetNamespace('BooJs.Lang'), # TODO: Do we actually need this ?
TypeSystemServices.BuiltinsType
)
+
View
39 src/BooJs.Compiler/Steps/NormalizeMethodInvocation.boo
@@ -4,20 +4,57 @@ import Boo.Lang.Compiler
import Boo.Lang.Compiler.Ast
import Boo.Lang.Compiler.Steps
+import Boo.Lang.Environments
+import Boo.Lang.Compiler.TypeSystem.Services.RuntimeMethodCache as BooRuntimeMethodCache
+import BooJs.Compiler.TypeSystem(RuntimeMethodCache)
+
+
class NormalizeMethodInvocation(AbstractTransformerCompilerStep):
"""
Normalize method invocations to undo some of the instrumentation performend byte Boo's ProcessMethodBodies step.
Since Javascript is highly dynamic there is no need to call special interface methods for things like array access
or calling anonymous functions.
"""
+ [getter(MethodCache)]
+ private _methodCache as RuntimeMethodCache
+
+ [getter(BooMethodCache)]
+ private _booMethodCache as BooRuntimeMethodCache
+
+ def Initialize(context as CompilerContext):
+ super(context)
+
+ _methodCache = EnvironmentProvision[of RuntimeMethodCache]()
+ _booMethodCache = EnvironmentProvision[of BooRuntimeMethodCache]()
def LeaveMethodInvocationExpression(node as MethodInvocationExpression):
""" We need to attach to the Leave hook since we sometimes have to replace the node """
+ # Map runtime methods inserted by Boo to our custom ones
+ target = node.Target
+ if target isa ReferenceExpression:
+ # Handle equality
+ if target.Entity is BooMethodCache.RuntimeServices_EqualityOperator:
+ mie = CodeBuilder.CreateMethodInvocation(MethodCache.RuntimeEquality, node.Arguments[0], node.Arguments[1])
+ ReplaceCurrentNode mie
+ return
+ elif target.Entity is BooMethodCache.RuntimeServices_GetEnumerable:
+ mie = CodeBuilder.CreateMethodInvocation(MethodCache.RuntimeEnumerable, node.Arguments[0])
+
+ # Retarget builtins
+ elif target.Entity and TypeSystemServices.IsBuiltin(target.Entity):
+ if target.NodeType == NodeType.MemberReferenceExpression:
+ (target as MemberReferenceExpression).Target = [| Boo |]
+ else:
+ (target as ReferenceExpression).Name = 'Boo.' + (target as ReferenceExpression).Name
+ return
+
+ /*
if node.Target isa MemberReferenceExpression:
NormalizeTarget(node, node.Target as MemberReferenceExpression)
elif node.Target isa ReferenceExpression:
NormalizeTarget(node, node.Target as ReferenceExpression)
+ */
/*
# Revert: CompilerGenerated.__FooModule_foo$callable0$7_9__(xxx, __addressof__(FooModule.$foo$closure$1))
@@ -32,7 +69,7 @@ class NormalizeMethodInvocation(AbstractTransformerCompilerStep):
private def NormalizeTarget(node as MethodInvocationExpression, target as MemberReferenceExpression):
# Convert: Boo.Lang.RuntimeServices.xxx -> Boo.xxx
- if target.Target.ToString() == 'Boo.Lang.Runtime.RuntimeServices':
+ if false and target.Target.ToString() == 'Boo.Lang.Runtime.RuntimeServices':
name = target.Name
if name == 'EqualityOperator':
View
38 src/BooJs.Compiler/Steps/OverrideProcessMethodBodies.boo
@@ -3,8 +3,10 @@ namespace BooJs.Compiler.Steps
import Boo.Lang.Compiler.Steps
import Boo.Lang.Compiler.Ast
import Boo.Lang.Compiler.TypeSystem
+import Boo.Lang.Compiler.TypeSystem(ExternalMethod, IExternalEntity)
import Boo.Lang.Environments
+import BooJs.Compiler.TypeSystem(RuntimeMethodCache)
class OverrideProcessMethodBodies(ProcessMethodBodiesWithDuckTyping):
""" Overrides some methods of the step to skip some modification made originally
@@ -38,6 +40,42 @@ class OverrideProcessMethodBodies(ProcessMethodBodiesWithDuckTyping):
override def Initialize(context as Boo.Lang.Compiler.CompilerContext):
super(context)
+ #override protected def ProcessInvocationOnUnknownCallableExpression(node as MethodInvocationExpression):
+ # print node
+ override def OnMethodInvocationExpression(node as MethodInvocationExpression):
+
+ super(node)
+
+ # HACK: The ICallable interface declares a generic Call method with object arguments
+ # and return type. In order to support jQuery style APIs we detect the ICallable
+ # trying to modify it by using a better match among the methods named Call in
+ # the declarting type.
+ target = node.Target as MemberReferenceExpression
+ if target and target.Entity == MethodCache.ICallable_Call:
+ # Find the original declaring type and fetch all its Call methods
+ type = target.Target.ExpressionType as Reflection.ExternalType
+ methods = List[of IMethod]()
+ for member in type.GetMembers():
+ if member isa ExternalMethod and member.Name == 'Call':
+ methods.Add(member)
+
+ # Resolve the best match among the Call methods for the given params
+ args = (node.Arguments[0] as ArrayLiteralExpression).Items
+ resolved as ExternalMethod = CallableResolutionService.ResolveCallableReference(args, methods.ToArray())
+ if resolved:
+ BindExpressionType(node, resolved.ReturnType)
+ BindExpressionType(node.Target, resolved.Type)
+
+ # Detect invokes for internal callables
+ if target and target.Entity:
+ targetType = target.Entity as Internal.InternalMethod
+ if targetType:
+ invoke as IMethod = ResolveMethod(targetType.DeclaringType, 'Invoke')
+ if invoke is targetType:
+ node.Target = target.Target
+
+ return
+
override def LeaveUnaryExpression(node as UnaryExpression):
# Increment/Decrement operators are resolved using a fairly complex eval. Since
# JS supports this operators natively we can simplify the case by just binding
View
4 src/BooJs.Compiler/Steps/PrintJs.boo
@@ -647,14 +647,14 @@ class BooJsPrinterVisitor(Visitors.TextEmitter):
WriteLine 'continue;'
def OnCastExpression(node as CastExpression):
- Write 'Boo.Lang.cast('
+ Write 'Boo.cast('
Visit node.Target
Write ', '
Visit node.Type
Write ')'
def OnTryCastExpression(node as TryCastExpression):
- Write 'Boo.Lang.trycast('
+ Write 'Boo.trycast('
Visit node.Target
Write ', '
Visit node.Type
View
4 src/BooJs.Compiler/TypeSystem/ReflectionProvider.boo
@@ -16,7 +16,9 @@ class ReflectionProvider(BooProvider):
override def IsAssignableFrom(other as IType) as bool:
external = other as ExternalType;
- return false if external is null
+ return true if external is null
+ return true if external is other
+ return true if external.IsAssignableFrom(other)
return external.ActualType != Types.Void;
internal class JsValueType(ExternalType):
View
54 src/BooJs.Compiler/TypeSystem/RuntimeMethodCache.boo
@@ -0,0 +1,54 @@
+# DEPRECATED: this approach never worked. It's not possible to override the original class used
+# in ProcessMethodBodies :(
+
+namespace BooJs.Compiler.TypeSystem
+
+import System
+import System.Collections.Generic
+import System.Reflection
+
+import Boo.Lang.Compiler.Util
+import Boo.Lang.Compiler(AbstractCompilerComponent)
+
+import Boo.Lang.Compiler.TypeSystem(IMethod, IMethodBase, IConstructor)
+import Boo.Lang.Compiler.TypeSystem.Services.RuntimeMethodCache as BooRuntimeMethodCache
+
+import BooJs.Lang.Runtime.Services as RuntimeServices
+
+class RuntimeMethodCache(AbstractCompilerComponent): #(BooRuntimeMethodCache):
+
+ #RuntimeServices_EqualityOperator as IMethod:
+ # get: return CachedMethod('RuntimeServices_EqualityOperator', {
+ # Methods.Of[of object, object, bool](RuntimeServices.Equality) #as IMethodBase
+ # })
+ # HACK: Boo converts property getters to this method name, since we can't overload
+ # non virtual properties we do this to shadow them
+ new def get_RuntimeServices_EqualityOperator() as IMethod:
+ return CachedMethod('RuntimeServices_EqualityOperator', {
+ Methods.Of[of object, object, bool](RuntimeServices.Equality) #as IMethodBase
+ })
+
+ RuntimeEquality as IMethod:
+ get: return CachedMethod('op_Equality', {
+ Methods.Of[of object, object, bool](RuntimeServices.Equality)
+ })
+
+ RuntimeEnumerable as IMethod:
+ get: return CachedMethod('enumerable', {
+ Methods.Of[of object, object, bool](RuntimeServices.Equality)
+ })
+
+
+ private _methodCache = Dictionary[of string, IMethodBase](StringComparer.Ordinal)
+ def CachedMethod(key as string, producer as callable() as MethodInfo) as IMethod:
+ return CachedMethodBase(key, { TypeSystemServices.Map(producer()) })
+
+ def CachedConstructor(key as string, producer as callable() as IMethodBase) as IConstructor:
+ return CachedMethodBase(key, producer)
+
+ protected def CachedMethodBase(key as string, producer as callable() as IMethodBase) as IMethodBase:
+ method as IMethodBase
+ if not _methodCache.TryGetValue(key, method):
+ method = producer()
+ _methodCache.Add(key, method)
+ return method
View
5 src/BooJs.Compiler/TypeSystem/Services.boo
@@ -1,6 +1,6 @@
namespace BooJs.Compiler.TypeSystem
-import Boo.Lang.Compiler.TypeSystem(BuiltinFunction)
+import Boo.Lang.Compiler.TypeSystem(BuiltinFunction, IType)
import Boo.Lang.Compiler.TypeSystem.TypeSystemServices as BooServices
import BooJs.Lang
@@ -22,7 +22,7 @@ class Services(BooServices):
UIntType = Map(Globals.NumberUInt)
DoubleType = Map(Globals.NumberDouble)
RegExpType = Map(Globals.RegExp)
- ICallableType = Map(Globals.Function)
+ ICallableType = Map(ICallable) #Map(Globals.Function)
DuckType = Map(Builtins.Duck)
RuntimeServicesType = Map(Runtime.Services)
@@ -50,7 +50,6 @@ class Services(BooServices):
#AddBuiltin(BuiltinFunction.Switch);
-
/*
# We might need to replace more methods to take into account the new types
new def IsNumberOrBool(type as IType):
View
1 src/BooJs.Lang/Dom2.boo
@@ -5,7 +5,6 @@ Ref: http://www.w3.org/TR/DOM-Level-2-Core/idl-definitions.html
"""
namespace BooJs.Lang.Dom2
-
interface Node:
/*
static final ELEMENT_NODE as ushort = 1
View
22 src/BooJs.Lang/Globals/Array.boo
@@ -1,7 +1,29 @@
namespace BooJs.Lang.Globals
+import BooJs.Lang.Extensions
+
class Array(Object):
+ [JsAlias('Boo.Array.op_Equality')]
+ static def op_Equality(lhs as Array, rhs as Array) as bool:
+ pass
+ [JsAlias('Boo.Array.op_Equality')]
+ static def op_Equality(lhs as object*, rhs as object*) as bool:
+ pass
+ [JsAlias('Boo.Array.op_Member')]
+ static def op_Member(lhs as Array, rhs as object) as bool:
+ pass
+ [JsRewrite('!Boo.Array.op_Member($1, $2)')]
+ static def op_NotMember(lhs as Array, rhs as object) as bool:
+ pass
+ [JsAlias('Boo.Array.op_Addition')]
+ static def op_Addition(lhs as Array, rhs as Array) as Array:
+ pass
+ [JsAlias('Boo.Array.op_Multiply')]
+ static def op_Multiply(lhs as Array, rhs as int) as Array:
+ pass
+
+
#self[index as int] as object:
# get: pass
# set: pass
View
45 src/BooJs.Lang/Globals/Number.boo
@@ -1,5 +1,7 @@
namespace BooJs.Lang.Globals
+import BooJs.Lang.Extensions
+
class Number(Object):
static final NaN as double
@@ -9,11 +11,6 @@ class Number(Object):
static final POSITIVE_INFINITY as double
- def constructor():
- pass
- def constructor(n as double):
- pass
-
def toExponential(digits as int) as string:
pass
def toExponential() as string:
@@ -30,11 +27,43 @@ class Number(Object):
def toString(radix as int) as string:
pass
+
class NumberInt(Number):
- pass
+ # Handle integer divisions
+ [JsRewrite('parseInt($1 / $2)')]
+ static def op_Division(lhs as int, rhs as int) as int:
+ pass
+ # Exponentiation
+ [JsRewrite('Math.pow($1, $2)')]
+ static def op_Exponentiation(lhs as int, rhs as int) as int:
+ pass
+
+ [JsRewrite('Boo.String.op_Multiply($2, $1)')]
+ static def op_Multiply(lhs as int, rhs as string) as string:
+ pass
+
+ def constructor():
+ pass
+
+ def constructor(n as object):
+ pass
class NumberUInt(NumberInt):
- pass
+ def constructor():
+ pass
+
+ def constructor(n as object):
+ pass
+
class NumberDouble(Number):
- pass
+ # Exponentiation
+ [JsRewrite('Math.pow($1, $2)')]
+ static def op_Exponentiation(lhs as double, rhs as double) as double:
+ pass
+
+ def constructor():
+ pass
+ # TODO: We might want to be more strict on this calling a runtime method
+ def constructor(n as object):
+ pass
View
22 src/BooJs.Lang/Globals/String.boo
@@ -1,7 +1,29 @@
namespace BooJs.Lang.Globals
+import BooJs.Lang.Extensions
class String(Object):
+ # IMPORTANT: Boo requires explicit/implicit operators to use the actual types
+ static def op_Explicit(value as String) as NumberInt:
+ pass
+
+ [JsRewrite('$1 == $2')]
+ static def op_Equality(lhs as string, rhs as string) as bool:
+ pass
+
+ [JsRewrite('$1 + $2')]
+ static def op_Addition(lhs as string, rhs as string) as string:
+ pass
+
+ # Multiply operator: 'foo' * 2 --> 'foofoo'
+ [JsAlias('Boo.String.op_Multiply')]
+ static def op_Multiply(lhs as string, rhs as int) as string:
+ pass
+ # Formatting: '{0} {1}' % ('foo', 'bar')
+ [JsAlias('Boo.String.op_Modulus')]
+ static def op_Modulus(lhs as string, rhs as object*) as string:
+ pass
+
# Static methods
View
56 src/BooJs.Lang/Runtime/Services.boo
@@ -5,6 +5,16 @@ import BooJs.Lang.Extensions
class Services:
+
+ [JsRewrite('Boo.op_Equality($1, $2)')]
+ static def Equality(lhs as object, rhs as object) as bool:
+ pass
+
+ [JsAlias('Boo.enumerable')]
+ static def Enumerable(list as object) as bool:
+ pass
+
+
# HACK: We name the methods differently since we don't have a clean way
# to resolve an overloaded method based on their params from the
# compiler step, so this simplifies their use.
@@ -21,62 +31,16 @@ class Services:
# TODO: When any type doesn't have a explicit operator overload they seem to use the ones from other types :-s
- # Multiply operator: 'foo' * 2 --> 'foofoo'
- [JsAlias('Boo.String.op_Multiply')]
- [Extension] static def op_Multiply(lhs as string, rhs as int) as string:
- pass
- [JsRewrite('Boo.String.op_Multiply($2, $1)')]
- [Extension] static def op_Multiply(lhs as int, rhs as string) as string:
- pass
- # Formatting: '{0} {1}' % ('foo', 'bar')
- [JsAlias('Boo.String.op_Modulus')]
- [Extension] static def op_Modulus(lhs as string, rhs as object*) as string:
- pass
- # Handle integer divisions
- [JsRewrite('parseInt($1 / $2)')]
- [Extension] static def op_Division(lhs as int, rhs as int) as int:
- pass
- # Exponentiation
- [JsRewrite('Math.pow($1, $2)')]
- [Extension] static def op_Exponentiation(lhs as int, rhs as int) as int:
- pass
- [JsRewrite('Math.pow($1, $2)')]
- [Extension] static def op_Exponentiation(lhs as double, rhs as double) as double:
- pass
# TODO: We need to think how strings are handled when used like numbers
[JsRewrite('$1 == $2')]
[Extension] static def op_Equality(lhs as double, rhs as string) as bool:
pass
- [JsRewrite('$1 == $2')]
- [Extension] static def op_Equality(lhs as string, rhs as string) as bool:
- pass
[JsRewrite('$1 + $2')]
[Extension] static def op_Addition(lhs as double, rhs as string) as string:
pass
[JsRewrite('$1 + $2')]
[Extension] static def op_Addition(lhs as string, rhs as double) as string:
pass
-
- # Array
- [JsAlias('Boo.Array.op_Equality')]
- [Extension] static def op_Equality(lhs as Array, rhs as Array) as bool:
- pass
- [JsAlias('Boo.Array.op_Equality')]
- [Extension] static def op_Equality(lhs as object*, rhs as object*) as bool:
- pass
- [JsAlias('Boo.Array.op_Member')]
- [Extension] static def op_Member(lhs as Array, rhs as object) as bool:
- pass
- [JsRewrite('!Boo.Array.op_Member($1, $2)')]
- [Extension] static def op_NotMember(lhs as Array, rhs as object) as bool:
- pass
- [JsAlias('Boo.Array.op_Addition')]
- [Extension] static def op_Addition(lhs as Array, rhs as Array) as Array:
- pass
- [JsAlias('Boo.Array.op_Multiply')]
- [Extension] static def op_Multiply(lhs as Array, rhs as int) as Array:
- pass
-
View
35 src/BooJs.Lang/jQuery.boo
@@ -57,21 +57,36 @@ class jQuery(ICallable):
selector as string:
get: pass
+ def constructor():
+ pass
+ def constructor(expr_or_html as string):
+ pass
+ def constructor(expression as string, context as jQuery):
+ pass
+ def constructor(html as string, document as DOM.Document):
+ pass
+ def constructor(element as DOM.Element):
+ pass
+ def constructor(elements as (DOM.Element)):
+ pass
+ def constructor(callback as callable):
+ pass
# Callable interface
def Call(args as (object)) as object:
+ return args[0] cast jQuery
+ # callable methods for BooJs
+ def Call(expr_or_html as string) as jQuery:
pass
- def Call(expression as string, context as jQuery) as jQuery:
- pass
- def Call(expr_or_html as string) as jQuery:
+ def Call(expression as string, context as jQuery) as jQuery:
pass
- def Call(html as string, document as DOM.Document) as jQuery:
+ def Call(html as string, document as DOM.Document) as jQuery:
pass
- def Call(element as DOM.Element) as jQuery:
+ def Call(element as DOM.Element) as jQuery:
pass
- def Call(elements as (DOM.Element)) as jQuery:
+ def Call(elements as (DOM.Element)) as jQuery:
pass
- def Call(callback as callable) as jQuery:
+ def Call(callback as callable) as jQuery:
pass
# Core - Accessors
@@ -80,9 +95,12 @@ class jQuery(ICallable):
def index(subject as DOM.Element) as int:
pass
- def each(callback as callable) as jQuery:
+ #def each(callback as callable(object)) as jQuery:
+ # pass
+ def each(callback as callable) as jQuery:
pass
+
def size() as uint:
pass
@@ -264,3 +282,4 @@ class jQuery(ICallable):
pass
# .......
+
View
7 tests/fixtures/typesystem/jquery.boo
@@ -0,0 +1,7 @@
+import jQuery
+
+jQuery('.foo').each({itm| print itm})
+
+jq = jQuery()
+
+jq('.foo').each({itm| print itm })
View
7 tests/fixtures/typesystem/native-types.boo
@@ -1,7 +1,7 @@
"""
0
string null
-list null
+Array null
regex True
object 2
duck foo1
@@ -16,11 +16,8 @@ print a + b + c
d as string
print 'string', d
-#e as List # List type is not supported, only mutable arrays
-#print e
-
# Arrays are mutable in Javascript thus it's init as null
-f as list
+f as Array
print 'list', f
r as regex = /foo/
View
4 tests/fixtures/typesystem/numbers.boo
@@ -10,6 +10,6 @@ d as double = 0.10
print i + u + d
print i * u + d
-# Check implicit conversion from string
+# Check conversion from string
s as string = '5'
-print u * s + d
+print u * (s cast int) + d
View
1 tests/fixtures/typesystem/version.boo
@@ -2,4 +2,5 @@
@
"""
+
assert len(BOO_RUNTIME_VERSION) > 0

0 comments on commit 986b4e4

Please sign in to comment.
Something went wrong with that request. Please try again.