Front page | perl.cvs.parrot |
Postings from December 2008
[svn:parrot] r34320 - in trunk/languages/ecmascript: . config/makefiles src/builtin src/classes src/parser t
From:
tewk
Date:
December 24, 2008 00:09
Subject:
[svn:parrot] r34320 - in trunk/languages/ecmascript: . config/makefiles src/builtin src/classes src/parser t
Message ID:
20081224080925.D0FFBCBA12@x12.develooper.com
Author: tewk
Date: Wed Dec 24 00:09:24 2008
New Revision: 34320
Added:
trunk/languages/ecmascript/src/classes/
trunk/languages/ecmascript/src/classes/Boolean.pir
trunk/languages/ecmascript/src/classes/Completion.pir
trunk/languages/ecmascript/src/classes/List.pir
trunk/languages/ecmascript/src/classes/Null.pir
trunk/languages/ecmascript/src/classes/Number.pir
trunk/languages/ecmascript/src/classes/Object.pir
trunk/languages/ecmascript/src/classes/Reference.pir
trunk/languages/ecmascript/src/classes/String.pir
trunk/languages/ecmascript/src/classes/Undefined.pir
trunk/languages/ecmascript/t/02-sanity-var.t
trunk/languages/ecmascript/t/03-boolean.t
Modified:
trunk/languages/ecmascript/config/makefiles/root.in
trunk/languages/ecmascript/js.pir
trunk/languages/ecmascript/src/builtin/builtins.pir
trunk/languages/ecmascript/src/parser/actions.pm
trunk/languages/ecmascript/src/parser/grammar.pg
Log:
[js] the beginning of core types
Modified: trunk/languages/ecmascript/config/makefiles/root.in
==============================================================================
--- trunk/languages/ecmascript/config/makefiles/root.in (original)
+++ trunk/languages/ecmascript/config/makefiles/root.in Wed Dec 24 00:09:24 2008
@@ -41,6 +41,12 @@
src/gen_grammar.pir \
src/gen_actions.pir \
src/builtin/builtins.pir \
+ src/classes/Object.pir \
+ src/classes/Null.pir \
+ src/classes/Boolean.pir \
+ src/classes/Number.pir \
+ src/classes/String.pir \
+ src/classes/Undefined.pir \
#PMCS = \
# jsobject \
Modified: trunk/languages/ecmascript/js.pir
==============================================================================
--- trunk/languages/ecmascript/js.pir (original)
+++ trunk/languages/ecmascript/js.pir Wed Dec 24 00:09:24 2008
@@ -80,6 +80,12 @@
.namespace []
.include 'src/builtin/builtins.pir'
+.include 'src/classes/Object.pir'
+.include 'src/classes/Boolean.pir'
+.include 'src/classes/Null.pir'
+#.include 'src/classes/Number.pir'
+#.include 'src/classes/String.pir'
+#.include 'src/classes/Undefined.pir'
# Local Variables:
Modified: trunk/languages/ecmascript/src/builtin/builtins.pir
==============================================================================
--- trunk/languages/ecmascript/src/builtin/builtins.pir (original)
+++ trunk/languages/ecmascript/src/builtin/builtins.pir Wed Dec 24 00:09:24 2008
@@ -15,8 +15,28 @@
print $P1
goto print_loop
end_print_loop:
+ print "\n"
.end
+.sub 'version'
+ .param pmc version :optional
+ .param int has_version :opt_flag
+
+ $P1 = get_global '+$VERSION'
+ if_null $P1, unnullit
+ unless has_version goto ret
+ set_global '+$VERSION', version
+ ret:
+ .return ($P1)
+ unnullit:
+# $P1 = new 'Integer'
+ $P1 = box 0
+ set_global '+$VERSION', $P1
+ .return ($P1)
+.end
+
+
+
## constructor for a object literals. It takes advantages of
## the Parrot Calling Conventions using :slurpy and :named flags,
## meaning that the parameter C<fields> is a hash, which is kinda
@@ -313,6 +333,14 @@
.sub 'prefix:typeof'
.param pmc op
+ $S0 = typeof op
+
+ $S1 = 'unknown'
+ ne $S0, 'Sub', n1
+ $S1 = 'function'
+ n1:
+
+ .return ($S1)
.end
.sub 'prefix:+'
Added: trunk/languages/ecmascript/src/classes/Boolean.pir
==============================================================================
--- (empty file)
+++ trunk/languages/ecmascript/src/classes/Boolean.pir Wed Dec 24 00:09:24 2008
@@ -0,0 +1,69 @@
+## $Id: Bool.pir 32793 2008-11-18 03:21:53Z particle $
+
+=head1 TITLE
+
+Bool - Javascript Boolean Type and values
+
+=head1 DESCRIPTION
+
+This file sets up the Javascript C<Boolean> type, and initializes
+symbols for C<Boolean::True> and C<Boolean::False>.
+
+=head1 Methods
+
+=over 4
+
+=cut
+
+.namespace ['JSBoolean']
+
+.sub 'onload' :anon :init :load
+ .local pmc jsmeta, boolproto
+ jsmeta = get_hll_global ['JSObject'], '$!JSMETA'
+ boolproto = jsmeta.'new_class'('JSBoolean', 'parent'=>'Boolean')
+ #boolproto = jsmeta.'new_class'('Boolean')
+ #boolproto.'!IMMUTABLE'()
+ jsmeta.'register'('Boolean', 'parent'=>boolproto, 'protoobject'=>boolproto)
+
+ $P0 = boolproto.'new'()
+ $P0 = 0
+ set_hll_global ['JSBoolean'], 'false', $P0
+
+ $P0 = boolproto.'new'()
+ $P0 = 1
+ set_hll_global ['JSBoolean'], 'true', $P0
+.end
+
+.sub 'get_string' :vtable
+ .param pmc self
+ $I0 = self
+ unless self goto f
+ .return ("true")
+ f:
+ .return ("false")
+.end
+
+.sub 'ACCEPTS' :method
+ .param pmc topic
+ .return (self)
+.end
+
+
+.sub 'js' :method
+ if self goto false
+ .return ('false')
+ false:
+ .return ('true')
+.end
+
+
+=back
+
+=cut
+
+
+# Local Variables:
+# mode: pir
+# fill-column: 100
+# End:
+# vim: expandtab shiftwidth=4 ft=pir:
Added: trunk/languages/ecmascript/src/classes/Completion.pir
==============================================================================
--- (empty file)
+++ trunk/languages/ecmascript/src/classes/Completion.pir Wed Dec 24 00:09:24 2008
@@ -0,0 +1,90 @@
+## $Id: Completion.pir 33898 2008-12-14 19:56:12Z pmichaud $
+
+=head1 NAME
+
+src/classes/Completion.pir - Completion objects
+
+=head1 DESCRIPTION
+
+=cut
+
+.namespace []
+
+.sub '' :anon :load :init
+ .local pmc jsmeta, nilproto
+ jsmeta = get_hll_global ['JSObject'], '$!JSMETA'
+ nilproto = jsmeta.'new_class'('Completion', 'parent'=>'Failure')
+ $P0 = nilproto.'new'()
+ set_hll_global ['Undefined'], 'undef', $P0
+ .end
+.end
+
+=head2 Methods
+
+=over
+
+=item 'list'
+
+=cut
+
+.namespace ['Completion']
+.sub 'list' :method
+ $P0 = new 'List'
+ .return ($P0)
+.end
+
+
+=item 'shift'
+
+=cut
+
+.namespace ['Completion']
+.sub 'shift' :method :vtable('shift_pmc')
+ .return (self)
+.end
+
+=back
+
+=head2 Coercion methods
+
+=over
+
+=item Scalar
+
+=cut
+
+.namespace ['Completion']
+.sub 'Scalar' :method
+ $P0 = new 'Failure'
+ .return ($P0)
+.end
+
+
+=back
+
+=head2 Private methods
+
+=over
+
+=item !flatten
+
+Return an empty list when flattened.
+
+=cut
+
+.namespace ['Completion']
+.sub '!flatten' :method
+ .tailcall self.'list'()
+.end
+
+
+=back
+
+=cut
+
+# Local Variables:
+# mode: pir
+# fill-column: 100
+# End:
+# vim: expandtab shiftwidth=4 ft=pir:
+
Added: trunk/languages/ecmascript/src/classes/List.pir
==============================================================================
--- (empty file)
+++ trunk/languages/ecmascript/src/classes/List.pir Wed Dec 24 00:09:24 2008
@@ -0,0 +1,90 @@
+## $Id: Nil.pir 33898 2008-12-14 19:56:12Z pmichaud $
+
+=head1 NAME
+
+src/classes/List.pir - List objects
+
+=head1 DESCRIPTION
+
+=cut
+
+.namespace []
+
+.sub '' :anon :load :init
+ .local pmc jsmeta, nilproto
+ jsmeta = get_hll_global ['JSObject'], '$!JSMETA'
+ nilproto = jsmeta.'new_class'('List', 'parent'=>'Failure')
+ $P0 = nilproto.'new'()
+ set_hll_global ['List'], 'undef', $P0
+ .end
+.end
+
+=head2 Methods
+
+=over
+
+=item 'list'
+
+=cut
+
+.namespace ['Nil']
+.sub 'list' :method
+ $P0 = new 'List'
+ .return ($P0)
+.end
+
+
+=item 'shift'
+
+=cut
+
+.namespace ['Nil']
+.sub 'shift' :method :vtable('shift_pmc')
+ .return (self)
+.end
+
+=back
+
+=head2 Coercion methods
+
+=over
+
+=item Scalar
+
+=cut
+
+.namespace ['Nil']
+.sub 'Scalar' :method
+ $P0 = new 'Failure'
+ .return ($P0)
+.end
+
+
+=back
+
+=head2 Private methods
+
+=over
+
+=item !flatten
+
+Return an empty list when flattened.
+
+=cut
+
+.namespace ['Nil']
+.sub '!flatten' :method
+ .tailcall self.'list'()
+.end
+
+
+=back
+
+=cut
+
+# Local Variables:
+# mode: pir
+# fill-column: 100
+# End:
+# vim: expandtab shiftwidth=4 ft=pir:
+
Added: trunk/languages/ecmascript/src/classes/Null.pir
==============================================================================
--- (empty file)
+++ trunk/languages/ecmascript/src/classes/Null.pir Wed Dec 24 00:09:24 2008
@@ -0,0 +1,91 @@
+## $Id: Nil.pir 33898 2008-12-14 19:56:12Z pmichaud $
+
+=head1 NAME
+
+src/classes/Nil.pir - Nil objects
+
+=head1 DESCRIPTION
+
+=cut
+
+.namespace []
+
+.sub '' :anon :load :init
+ .local pmc jsmeta, nilproto
+ jsmeta = get_hll_global ['JSObject'], '$!JSMETA'
+ nilproto = jsmeta.'new_class'('JSNull', 'parent'=>'Null')
+ jsmeta.'register'('Null', 'parent'=>nilproto, 'protoobject'=>nilproto)
+
+ $P0 = nilproto.'new'()
+ set_hll_global ['Null'], 'null', $P0
+ .end
+
+=head2 Methods
+
+=over
+
+=item 'list'
+
+=cut
+
+.namespace ['Nil']
+.sub 'list' :method
+ $P0 = new 'List'
+ .return ($P0)
+.end
+
+
+=item 'shift'
+
+=cut
+
+.namespace ['Nil']
+.sub 'shift' :method :vtable('shift_pmc')
+ .return (self)
+.end
+
+=back
+
+=head2 Coercion methods
+
+=over
+
+=item Scalar
+
+=cut
+
+.namespace ['Nil']
+.sub 'Scalar' :method
+ $P0 = new 'Failure'
+ .return ($P0)
+.end
+
+
+=back
+
+=head2 Private methods
+
+=over
+
+=item !flatten
+
+Return an empty list when flattened.
+
+=cut
+
+.namespace ['Nil']
+.sub '!flatten' :method
+ .tailcall self.'list'()
+.end
+
+
+=back
+
+=cut
+
+# Local Variables:
+# mode: pir
+# fill-column: 100
+# End:
+# vim: expandtab shiftwidth=4 ft=pir:
+
Added: trunk/languages/ecmascript/src/classes/Number.pir
==============================================================================
--- (empty file)
+++ trunk/languages/ecmascript/src/classes/Number.pir Wed Dec 24 00:09:24 2008
@@ -0,0 +1,104 @@
+## $Id: Num.pir 32597 2008-11-13 08:04:20Z pmichaud $
+
+=head1 TITLE
+
+Num - JS numbers
+
+=head1 SUBROUTINES
+
+=over 4
+
+=item onload()
+
+=cut
+
+.namespace [ 'Num' ]
+
+.sub 'onload' :anon :init :load
+ .local pmc jsmeta, numproto
+ jsmeta = get_hll_global ['JSObject'], '$!JSMETA'
+ numproto = jsmeta.'new_class'('Num', 'parent'=>'Float Any')
+ numproto.'!IMMUTABLE'()
+ jsmeta.'register'('Float', 'parent'=>numproto, 'protoobject'=>numproto)
+
+ # Override the proto's ACCEPT method so we also accept Ints.
+ .const 'Sub' $P0 = "Num::ACCEPTS"
+ $P1 = typeof numproto
+ $P1.'add_method'('ACCEPTS', $P0)
+.end
+
+
+.sub 'Num::ACCEPTS' :anon :method
+ .param pmc topic
+
+ ## first, try our superclass .ACCEPTS
+ $P0 = get_hll_global 'Any'
+ $P1 = find_method $P0, 'ACCEPTS'
+ $I0 = self.$P1(topic)
+ unless $I0 goto try_int
+ .return ($I0)
+
+ try_int:
+ $P0 = get_hll_global 'Int'
+ $I0 = $P0.'ACCEPTS'(topic)
+ .return ($I0)
+.end
+
+
+=item ACCEPTS()
+
+=cut
+
+.sub 'ACCEPTS' :method
+ .param num topic
+ .tailcall 'infix:=='(topic, self)
+.end
+
+
+=item js()
+
+Returns a JS representation of the Num.
+
+=cut
+
+.sub 'js' :method
+ $S0 = self
+ .return($S0)
+.end
+
+
+=item WHICH()
+
+Returns the identify value.
+
+=cut
+
+.sub 'WHICH' :method
+ $N0 = self
+ .return ($N0)
+.end
+
+
+=item infix:===
+
+Overridden for Num.
+
+=cut
+
+.namespace []
+.sub 'infix:===' :multi(Float,Float)
+ .param num a
+ .param num b
+ .tailcall 'infix:=='(a, b)
+.end
+
+
+=back
+
+=cut
+
+# Local Variables:
+# mode: pir
+# fill-column: 100
+# End:
+# vim: expandtab shiftwidth=4 ft=pir:
Added: trunk/languages/ecmascript/src/classes/Object.pir
==============================================================================
--- (empty file)
+++ trunk/languages/ecmascript/src/classes/Object.pir Wed Dec 24 00:09:24 2008
@@ -0,0 +1,759 @@
+## $Id: Object.pir 34029 2008-12-17 15:28:47Z jonathan $
+
+=head1 TITLE
+
+Object - JS Object class
+
+=head1 DESCRIPTION
+
+This file sets up the base classes and methods for JS's
+object system. Differences (and conflicts) between Parrot's
+object model and the JS model means we have to do a little
+name and method trickery here and there, and this file takes
+care of much of that.
+
+=cut
+
+.namespace []
+.sub '' :anon :init :load
+ .local pmc jsmeta
+ load_bytecode 'PCT.pbc'
+ $P0 = get_root_global ['parrot'], 'P6metaclass'
+ $P0.'new_class'('JSObject')
+ jsmeta = $P0.'HOW'()
+ set_hll_global ['JSObject'], '$!JSMETA', jsmeta
+.end
+
+=head2 Methods
+
+=over 4
+
+=item clone()
+
+Returns a copy of the object.
+
+NOTE: Don't copy what this method does; it's a tad inside-out. We should be
+overriding the clone vtable method to call .clone() really. But if we do that,
+we can't current get at the Object PMC's clone method, so for now we do it
+like this.
+
+=cut
+
+.namespace ['JSObject']
+.sub 'clone' :method
+ .param pmc new_attrs :slurpy :named
+
+ # Make a clone.
+ .local pmc result
+ $I0 = isa self, 'ObjectRef'
+ unless $I0 goto do_clone
+ self = deref self
+ do_clone:
+ result = clone self
+
+ # Set any new attributes.
+ .local pmc it
+ it = iter new_attrs
+ it_loop:
+ unless it goto it_loop_end
+ $S0 = shift it
+ $P0 = new_attrs[$S0]
+ $S0 = concat '!', $S0
+ $P1 = result.$S0()
+ 'infix:='($P1, $P0)
+ goto it_loop
+ it_loop_end:
+
+ .return (result)
+.end
+
+
+=item defined()
+
+Return true if the object is defined.
+
+=cut
+
+.namespace ['JSObject']
+.sub 'defined' :method
+ $P0 = get_hll_global ['Bool'], 'True'
+ .return ($P0)
+.end
+
+
+=item hash
+
+Return invocant in hash context.
+
+=cut
+
+.namespace ['JSObject']
+.sub 'hash' :method
+ .tailcall self.'Hash'()
+.end
+
+.namespace []
+.sub 'hash'
+ .param pmc values :slurpy
+ .tailcall values.'Hash'()
+.end
+
+=item item
+
+Return invocant in item context. Default is to return self.
+
+=cut
+
+.namespace ['JSObject']
+.sub 'item' :method
+ .return (self)
+.end
+
+.namespace []
+.sub 'item'
+ .param pmc x :slurpy
+ $I0 = elements x
+ unless $I0 == 1 goto have_x
+ x = shift x
+ have_x:
+ $I0 = can x, 'item'
+ unless $I0 goto have_item
+ x = x.'item'()
+ have_item:
+ .return (x)
+.end
+
+
+=item list
+
+Return invocant in list context. Default is to return a List containing self.
+
+=cut
+
+.namespace ['JSObject']
+.sub 'list' :method
+ $P0 = new 'List'
+ push $P0, self
+ .return ($P0)
+.end
+
+=item print()
+
+Print the object.
+
+=cut
+
+.namespace ['JSObject']
+.sub 'print' :method
+ $P0 = get_hll_global 'print'
+ .tailcall $P0(self)
+.end
+
+=item say()
+
+Print the object, followed by a newline.
+
+=cut
+
+.namespace ['JSObject']
+.sub 'say' :method
+ $P0 = get_hll_global 'say'
+ .tailcall $P0(self)
+.end
+
+=item true()
+
+Boolean value of object -- defaults to C<.defined> (S02).
+
+=cut
+
+.namespace ['JSObject']
+.sub 'true' :method
+ .tailcall self.'defined'()
+.end
+
+=back
+
+=head2 Coercion methods
+
+=over 4
+
+=item Array()
+
+=cut
+
+.namespace ['JSObject']
+.sub 'Array' :method
+ $P0 = new 'JSArray'
+ $P0.'!STORE'(self)
+ .return ($P0)
+.end
+
+=item Hash()
+
+=cut
+
+.namespace ['JSObject']
+.sub 'Hash' :method
+ $P0 = new 'JSHash'
+ $P0.'!STORE'(self)
+ .return ($P0)
+.end
+
+=item Iterator()
+
+=cut
+
+.sub 'Iterator' :method
+ $P0 = self.'list'()
+ .tailcall $P0.'Iterator'()
+.end
+
+=item Scalar()
+
+Default Scalar() gives reference type semantics, returning
+an object reference (unless the invocant already is one).
+
+=cut
+
+.namespace ['JSObject']
+.sub '' :method('Scalar') :anon
+ $I0 = isa self, 'ObjectRef'
+ unless $I0 goto not_ref
+ .return (self)
+ not_ref:
+ $P0 = new 'ObjectRef', self
+ .return ($P0)
+.end
+
+.namespace []
+.sub 'Scalar'
+ .param pmc source
+ $I0 = isa source, 'ObjectRef'
+ if $I0 goto done
+ $I0 = can source, 'Scalar'
+ if $I0 goto can_scalar
+ $I0 = does source, 'scalar'
+ source = new 'ObjectRef', source
+ done:
+ .return (source)
+ can_scalar:
+ .tailcall source.'Scalar'()
+.end
+
+=item Str()
+
+Return a string representation of the invocant. Default is
+the object's type and address.
+
+=cut
+
+.namespace ['JSObject']
+.sub 'Str' :method
+ $P0 = new 'ResizableStringArray'
+ $P1 = self.'WHAT'()
+ push $P0, $P1
+ $I0 = get_addr self
+ push $P0, $I0
+ $S0 = sprintf "%s<0x%x>", $P0
+ .return ($S0)
+.end
+
+=back
+
+=head2 Special methods
+
+=over 4
+
+=item new()
+
+Create a new object having the same class as the invocant.
+
+=cut
+
+.namespace ['JSObject']
+.sub 'new' :method
+ .param pmc init_parents :slurpy
+ .param pmc init_this :named :slurpy
+
+ # Instantiate.
+ .local pmc jsmeta
+ jsmeta = get_hll_global ['JSObject'], '$!JSMETA'
+ $P0 = jsmeta.'get_parrotclass'(self)
+ $P1 = new $P0
+
+ # If this proto object has a WHENCE auto-vivification, we should use
+ # put any values it contains but that init_this does not into init_this.
+ .local pmc whence
+ whence = self.'WHENCE'()
+ unless whence goto no_whence
+ .local pmc this_whence_iter
+ this_whence_iter = iter whence
+ this_whence_iter_loop:
+ unless this_whence_iter goto no_whence
+ $S0 = shift this_whence_iter
+ $I0 = exists init_this[$S0]
+ if $I0 goto this_whence_iter_loop
+ $P2 = whence[$S0]
+ init_this[$S0] = $P2
+ goto this_whence_iter_loop
+ no_whence:
+
+ # Now we will initialize each attribute in the class itself and it's
+ # parents with an Undef or the specified initialization value. Note that
+ # the all_parents list includes ourself.
+ .local pmc all_parents, class_iter
+ all_parents = inspect $P0, "all_parents"
+ class_iter = iter all_parents
+ class_iter_loop:
+ unless class_iter goto class_iter_loop_end
+ .local pmc cur_class
+ cur_class = shift class_iter
+
+ # If it's PMCProxy, then skip over it, since it's attribute is the delegate
+ # instance of a parent PMC class, which we should not change to Undef.
+ .local int is_pmc_proxy
+ is_pmc_proxy = isa cur_class, "PMCProxy"
+ if is_pmc_proxy goto class_iter_loop_end
+
+ # If this the current class?
+ .local pmc init_attribs
+ eq_addr cur_class, $P0, current_class
+
+ # If it's not the current class, need to see if we have any attributes.
+ # Go through the provided init_parents to see if we have anything that
+ # matches.
+ .local pmc ip_iter, cur_ip
+ ip_iter = iter init_parents
+ ip_iter_loop:
+ unless ip_iter goto ip_iter_loop_end
+ cur_ip = shift ip_iter
+
+ # We will check if their HOW matches.
+ $P2 = jsmeta.'get_parrotclass'(cur_ip)
+ eq_addr cur_class, $P2, found_parent_init
+
+ goto found_init_attribs
+ ip_iter_loop_end:
+
+ # If we get here, found nothing.
+ init_attribs = new 'Hash'
+ goto parent_init_search_done
+
+ # We found some parent init data, potentially.
+ found_parent_init:
+ init_attribs = cur_ip.'WHENCE'()
+ $I0 = 'defined'(init_attribs)
+ if $I0 goto parent_init_search_done
+ init_attribs = new 'Hash'
+ parent_init_search_done:
+ goto found_init_attribs
+
+ # If it's the current class, we will take the init_this hash.
+ current_class:
+ init_attribs = init_this
+ found_init_attribs:
+
+ # Now go through attributes of the current class and iternate over them.
+ .local pmc attribs, it
+ attribs = inspect cur_class, "attributes"
+ it = iter attribs
+ iter_loop:
+ unless it goto iter_end
+ $S0 = shift it
+
+ # See if we have an init value; use Undef if not.
+ .local int got_init_value
+ $S1 = substr $S0, 2
+ got_init_value = exists init_attribs[$S1]
+ if got_init_value goto have_init_value
+ $P2 = new 'Undef'
+ goto init_done
+ have_init_value:
+ $P2 = init_attribs[$S1]
+ delete init_attribs[$S1]
+ init_done:
+
+ # Is it a scalar? If so, want a scalar container with the type set on it.
+ .local string sigil
+ sigil = substr $S0, 0, 1
+ if sigil != '$' goto no_scalar
+ .local pmc attr_info, type
+ attr_info = attribs[$S0]
+ if null attr_info goto set_attrib
+ type = attr_info['type']
+ if null type goto set_attrib
+ if got_init_value goto no_proto_init
+ $I0 = isa type, 'P6protoobject'
+ unless $I0 goto no_proto_init
+ set $P2, type
+ no_proto_init:
+ $P2 = new 'JSScalar', $P2
+ setprop $P2, 'type', type
+ goto set_attrib
+ no_scalar:
+
+ # Is it an array? If so, initialize to JSArray.
+ if sigil != '@' goto no_array
+ $P3 = new 'JSArray'
+ $I0 = defined $P2
+ if $I0 goto have_array_value
+ set $P2, $P3
+ goto set_attrib
+ have_array_value:
+ 'infix:='($P3, $P2)
+ set $P2, $P3
+ goto set_attrib
+ no_array:
+
+ # Is it a Hash? If so, initialize to JSHash.
+ if sigil != '%' goto no_hash
+ $P3 = new 'JSHash'
+ $I0 = defined $P2
+ if $I0 goto have_hash_value
+ set $P2, $P3
+ goto set_attrib
+ have_hash_value:
+ 'infix:='($P3, $P2)
+ set $P2, $P3
+ goto set_attrib
+ no_hash:
+
+ set_attrib:
+ push_eh set_attrib_eh
+ setattribute $P1, cur_class, $S0, $P2
+ set_attrib_eh:
+ pop_eh
+ goto iter_loop
+ iter_end:
+
+ # Do we have anything left in the hash? If so, unknown.
+ $I0 = elements init_attribs
+ if $I0 == 0 goto init_attribs_ok
+ 'die'("You passed an initialization parameter that does not have a matching attribute.")
+ init_attribs_ok:
+
+ # Next class.
+ goto class_iter_loop
+ class_iter_loop_end:
+
+ .return ($P1)
+.end
+
+=item 'PARROT'
+
+Report the object's true nature.
+
+=cut
+
+.sub 'PARROT' :method
+ .local pmc obj
+ .local string result
+ obj = self
+ result = ''
+ $I0 = isa obj, 'ObjectRef'
+ unless $I0 goto have_obj
+ result = 'ObjectRef->'
+ obj = deref obj
+ have_obj:
+ $P0 = typeof obj
+ $S0 = $P0
+ result .= $S0
+ .return (result)
+.end
+
+
+=item REJECTS(topic)
+
+Define REJECTS methods for objects (this would normally
+be part of the Pattern role, but we put it here for now
+until we get roles).
+
+=cut
+
+.sub 'REJECTS' :method
+ .param pmc topic
+ $P0 = self.'ACCEPTS'(topic)
+ n_not $P0, $P0
+ .return ($P0)
+.end
+
+
+=item WHENCE()
+
+Return the invocant's auto-vivification closure.
+
+=cut
+
+.sub 'WHENCE' :method
+ $P0 = self.'WHAT'()
+ $P1 = $P0.'WHENCE'()
+ .return ($P1)
+.end
+
+
+=item WHERE
+
+Gets the memory address of the object.
+
+=cut
+
+.sub 'WHERE' :method
+ $I0 = get_addr self
+ .return ($I0)
+.end
+
+
+=item WHICH
+
+Gets the object's identity value
+
+=cut
+
+.sub 'WHICH' :method
+ # For normal objects, this can just be the memory address.
+ .tailcall self.'WHERE'()
+.end
+
+=back
+
+=head2 Private methods
+
+=over 4
+
+=item !cloneattr(attrlist)
+
+Create a clone of self, also cloning the attributes given by attrlist.
+
+=cut
+
+.namespace ['JSObject']
+.sub '!cloneattr' :method
+ .param string attrlist
+ .local pmc jsmeta, result
+ jsmeta = get_hll_global ['JSObject'], '$!JSMETA'
+ $P0 = jsmeta.'get_parrotclass'(self)
+ result = new $P0
+
+ .local pmc attr_it
+ attr_it = split ' ', attrlist
+ attr_loop:
+ unless attr_it goto attr_end
+ $S0 = shift attr_it
+ unless $S0 goto attr_loop
+ $P1 = getattribute self, $S0
+ if null $P1 goto null_attr
+ $P1 = clone $P1
+ null_attr:
+ setattribute result, $S0, $P1
+ goto attr_loop
+ attr_end:
+ .return (result)
+.end
+
+=item !.?
+
+Helper method for implementing the .? operator. Calls at most one matching
+method, and returns undef if there are none.
+
+=cut
+
+.sub '!.?' :method
+ .param string method_name
+ .param pmc pos_args :slurpy
+ .param pmc named_args :slurpy :named
+
+ # Get all possible methods.
+ .local pmc methods
+ methods = self.'!MANY_DISPATCH_HELPER'(method_name, pos_args, named_args)
+
+ # Do we have any?
+ $I0 = elements methods
+ if $I0 goto invoke
+ .tailcall '!FAIL'('Undefined value returned by invocation of undefined method')
+
+ # If we do have a method, call it.
+ invoke:
+ $P0 = methods[0]
+ .tailcall self.$P0(pos_args :flat, named_args :named :flat)
+.end
+
+=item !.*
+
+Helper method for implementing the .* operator. Calls one or more matching
+methods.
+
+=cut
+
+.sub '!.*' :method
+ .param string method_name
+ .param pmc pos_args :slurpy
+ .param pmc named_args :slurpy :named
+
+ # Get all possible methods.
+ .local pmc methods
+ methods = self.'!MANY_DISPATCH_HELPER'(method_name, pos_args, named_args)
+
+ # Build result capture list.
+ .local pmc pos_res, named_res, cap, result_list, it, cur_meth
+ $P0 = get_hll_global 'list'
+ result_list = $P0()
+ it = iter methods
+ it_loop:
+ unless it goto it_loop_end
+ cur_meth = shift it
+ (pos_res :slurpy, named_res :named :slurpy) = cur_meth(self, pos_args :flat, named_args :named :flat)
+ cap = 'prefix:\\'(pos_res :flat, named_res :flat :named)
+ push result_list, cap
+ goto it_loop
+ it_loop_end:
+
+ .return (result_list)
+.end
+
+
+=item !.+
+
+Helper method for implementing the .+ operator. Calls one or more matching
+methods, dies if there are none.
+
+=cut
+
+.sub '!.+' :method
+ .param string method_name
+ .param pmc pos_args :slurpy
+ .param pmc named_args :slurpy :named
+
+ # Use !.* to produce a (possibly empty) list of result captures.
+ .local pmc result_list
+ result_list = self.'!.*'(method_name, pos_args :flat, named_args :flat :named)
+
+ # If we got no elements at this point, we must die.
+ $I0 = elements result_list
+ if $I0 == 0 goto failure
+ .return (result_list)
+ failure:
+ $S0 = "Could not invoke method '"
+ concat $S0, method_name
+ concat $S0, "' on invocant of type '"
+ $S1 = self.'WHAT'()
+ concat $S0, $S1
+ concat $S0, "'"
+ 'die'($S0)
+.end
+
+
+=item !MANY_DISPATCH_HELPER
+
+This is a helper for implementing .+, .? and .*. In the future, it may well be
+the basis of WALK also. It returns all methods we could possible call.
+
+=cut
+
+.sub '!MANY_DISPATCH_HELPER' :method
+ .param string method_name
+ .param pmc pos_args
+ .param pmc named_args
+
+ # We need to find all methods we could call with the right name.
+ .local pmc jsmeta, result_list, class, mro, it
+ $P0 = get_hll_global 'list'
+ result_list = $P0()
+ jsmeta = get_hll_global ['JSObject'], '$!JSMETA'
+ class = self.'WHAT'()
+ class = jsmeta.'get_parrotclass'(class)
+ mro = inspect class, 'all_parents'
+ it = iter mro
+ mro_loop:
+ unless it goto mro_loop_end
+ .local pmc cur_class, meths, cur_meth
+ cur_class = shift it
+ meths = inspect cur_class, 'methods'
+ cur_meth = meths[method_name]
+ if null cur_meth goto mro_loop
+
+ # If we're here, found a method. But is it a multi?
+ $I0 = isa cur_meth, "JSMultiSub"
+ if $I0 goto multi_dispatch
+
+ # Single dispatch - add to the result list.
+ push result_list, cur_meth
+ goto mro_loop
+
+ # Multiple dispatch; get all applicable candidates.
+ multi_dispatch:
+ .local pmc possibles, possibles_it
+ possibles = cur_meth.'find_possible_candidates'(self, pos_args :flat)
+ possibles_it = iter possibles
+ possibles_it_loop:
+ unless possibles_it goto possibles_it_loop_end
+ cur_meth = shift possibles_it
+ push result_list, cur_meth
+ goto possibles_it_loop
+ possibles_it_loop_end:
+ goto mro_loop
+ mro_loop_end:
+
+ .return (result_list)
+.end
+
+=item !.^
+
+Helper for doing calls on the metaclass.
+
+=cut
+
+.sub '!.^' :method
+ .param string method_name
+ .param pmc pos_args :slurpy
+ .param pmc named_args :slurpy :named
+
+ # Get the HOW or the object and do the call on that.
+ .local pmc how
+ how = self.'HOW'()
+ .tailcall how.method_name(self, pos_args :flat, named_args :flat :named)
+.end
+
+=back
+
+=head2 Vtable functions
+
+=cut
+
+.namespace ['JSObject']
+.sub '' :vtable('decrement') :method
+ $P0 = self.'pred'()
+ 'infix:='(self, $P0)
+ .return(self)
+.end
+
+.sub '' :vtable('defined') :method
+ $I0 = self.'defined'()
+ .return ($I0)
+.end
+
+.sub '' :vtable('get_bool') :method
+ $I0 = self.'true'()
+ .return ($I0)
+.end
+
+.sub '' :vtable('get_iter') :method
+ .tailcall self.'Iterator'()
+.end
+
+.sub '' :vtable('get_string') :method
+ $S0 = self.'Str'()
+ .return ($S0)
+.end
+
+.sub '' :vtable('increment') :method
+ $P0 = self.'succ'()
+ 'infix:='(self, $P0)
+ .return(self)
+.end
+
+# Local Variables:
+# mode: pir
+# fill-column: 100
+# End:
+# vim: expandtab shiftwidth=4 ft=pir:
Added: trunk/languages/ecmascript/src/classes/Reference.pir
==============================================================================
--- (empty file)
+++ trunk/languages/ecmascript/src/classes/Reference.pir Wed Dec 24 00:09:24 2008
@@ -0,0 +1,90 @@
+## $Id: Nil.pir 33898 2008-12-14 19:56:12Z pmichaud $
+
+=head1 NAME
+
+src/classes/Reference.pir - Reference objects
+
+=head1 DESCRIPTION
+
+=cut
+
+.namespace []
+
+.sub '' :anon :load :init
+ .local pmc jsmeta, nilproto
+ jsmeta = get_hll_global ['JSObject'], '$!JSMETA'
+ nilproto = jsmeta.'new_class'('Reference', 'parent'=>'Failure')
+ $P0 = nilproto.'new'()
+ set_hll_global ['Reference'], 'undef', $P0
+ .end
+.end
+
+=head2 Methods
+
+=over
+
+=item 'list'
+
+=cut
+
+.namespace ['Nil']
+.sub 'list' :method
+ $P0 = new 'List'
+ .return ($P0)
+.end
+
+
+=item 'shift'
+
+=cut
+
+.namespace ['Nil']
+.sub 'shift' :method :vtable('shift_pmc')
+ .return (self)
+.end
+
+=back
+
+=head2 Coercion methods
+
+=over
+
+=item Scalar
+
+=cut
+
+.namespace ['Nil']
+.sub 'Scalar' :method
+ $P0 = new 'Failure'
+ .return ($P0)
+.end
+
+
+=back
+
+=head2 Private methods
+
+=over
+
+=item !flatten
+
+Return an empty list when flattened.
+
+=cut
+
+.namespace ['Nil']
+.sub '!flatten' :method
+ .tailcall self.'list'()
+.end
+
+
+=back
+
+=cut
+
+# Local Variables:
+# mode: pir
+# fill-column: 100
+# End:
+# vim: expandtab shiftwidth=4 ft=pir:
+
Added: trunk/languages/ecmascript/src/classes/String.pir
==============================================================================
--- (empty file)
+++ trunk/languages/ecmascript/src/classes/String.pir Wed Dec 24 00:09:24 2008
@@ -0,0 +1,230 @@
+## $Id: Str.pir 33714 2008-12-09 16:57:49Z pmichaud $
+
+=head1 TITLE
+
+Str - JS Str class and related functions
+
+=head1 DESCRIPTION
+
+This file sets up the C<JSStr> PMC type (from F<src/pmc/jsstr.pmc>)
+as the JS C<Str> class.
+
+=head1 Methods
+
+=over 4
+
+=cut
+
+.namespace ['Str']
+
+.include 'cclass.pasm'
+
+.sub 'onload' :anon :init :load
+ .local pmc jsmeta, strproto
+ jsmeta = get_hll_global ['JSObject'], '$!JSMETA'
+ strproto = jsmeta.'new_class'('Str', 'parent'=>'JS6Str Any')
+ strproto.'!IMMUTABLE'()
+ jsmeta.'register'('JS6Str', 'parent'=>strproto, 'protoobject'=>strproto)
+ jsmeta.'register'('String', 'parent'=>strproto, 'protoobject'=>strproto)
+
+ $P0 = get_hll_namespace ['Str']
+ '!EXPORT'('sprintf,reverse', 'from'=>$P0)
+.end
+
+
+## special method to cast Parrot String into Rakudo Str.
+.namespace ['String']
+.sub 'Scalar' :method
+ $P0 = new 'Str'
+ assign $P0, self
+ copy self, $P0
+ .return (self)
+.end
+
+
+.namespace ['Str']
+.sub 'ACCEPTS' :method
+ .param string topic
+ .tailcall 'infix:eq'(topic, self)
+.end
+
+
+.sub 'reverse' :method :multi('String')
+ .local pmc retv
+
+ retv = self.'split'('')
+ retv = retv.'reverse'()
+ retv = retv.'join'('')
+
+ .return(retv)
+.end
+
+
+
+=item js()
+
+Returns a js representation of the Str.
+
+=cut
+
+.sub 'js' :method
+ .local string str, result
+ str = self
+ result = '"'
+ .local int pos
+ pos = 0
+ .local pmc arr
+ arr = new 'ResizablePMCArray'
+ loop:
+ .local string ch
+ ch = substr str, pos, 1
+ if ch == '' goto done
+ if ch == ' ' goto loop_ch
+ ## check for special escapes
+ $I0 = index "$ @ % & { \b \n \r \t \\ \"", ch
+ if $I0 < 0 goto loop_nonprint
+ ch = substr "\\$\\@\\%\\&\\{\\b\\n\\r\\t\\\\\\\"", $I0, 2
+ goto loop_ch
+ loop_nonprint:
+ $I0 = is_cclass .CCLASS_PRINTING, ch, 0
+ if $I0 goto loop_ch
+ $I0 = ord ch
+ arr[0] = $I0
+ ch = sprintf '\x[%x]', arr
+ loop_ch:
+ result .= ch
+ inc pos
+ goto loop
+ done:
+ result .= '"'
+ .return (result)
+.end
+
+
+=item sprintf( *@args )
+
+=cut
+
+.sub 'sprintf' :method
+ .param pmc args :slurpy
+ args.'!flatten'()
+ $P0 = new 'Str'
+ sprintf $P0, self, args
+ .return ($P0)
+.end
+
+
+=item WHICH()
+
+Returns the identify value.
+
+=cut
+
+.sub 'WHICH' :method
+ $S0 = self
+ .return ($S0)
+.end
+
+
+=back
+
+=head1 Functions
+
+=over 4
+
+=cut
+
+.namespace []
+
+.include 'cclass.pasm'
+
+
+=item infix:===
+
+Overridden for Str.
+
+=cut
+
+.namespace []
+.sub 'infix:===' :multi(String,String)
+ .param string a
+ .param string b
+ .tailcall 'infix:eq'(a, b)
+.end
+
+
+=back
+
+=head2 TODO Functions
+
+=over 4
+
+=item p5chop
+
+ our Char multi P5emul::Str::p5chop ( Str $string is rw )
+ our Char multi P5emul::Str::p5chop ( Str *@strings = ($+_) is rw )
+
+Trims the last character from C<$string>, and returns it. Called with a
+list, it chops each item in turn, and returns the last character
+chopped.
+
+=item p5chomp
+
+ our Int multi P5emul::Str::p5chomp ( Str $string is rw )
+ our Int multi P5emul::Str::p5chomp ( Str *@strings = ($+_) is rw )
+
+Related to C<p5chop>, only removes trailing chars that match C</\n/>. In
+either case, it returns the number of chars removed.
+
+=item chomp
+
+ our Str method Str::chomp ( Str $string: )
+
+Returns string with newline removed from the end. An arbitrary
+terminator can be removed if the input filehandle has marked the
+string for where the "newline" begins. (Presumably this is stored
+as a property of the string.) Otherwise a standard newline is removed.
+
+Note: Most users should just let their I/O handles autochomp instead.
+(Autochomping is the default.)
+
+=item length
+
+This word is banned in JS. You must specify units.
+
+=item index
+
+Needs to be in terms of StrPos, not Int.
+
+=item pack
+
+=item pos
+
+=item quotemeta
+
+=item rindex
+
+Needs to be in terms of StrPos, not Int.
+
+=item sprintf
+
+=item unpack
+
+=item vec
+
+Should replace vec with declared arrays of bit, uint2, uint4, etc.
+
+=item words
+
+ our List multi Str::words ( Rule $matcher = /\S+/, Str $input = $+_, Int $limit = inf )
+ our List multi Str::words ( Str $input : Rule $matcher = /\S+/, Int $limit = inf )
+
+=back
+
+=cut
+
+# Local Variables:
+# mode: pir
+# fill-column: 100
+# End:
+# vim: expandtab shiftwidth=4 ft=pir:
Added: trunk/languages/ecmascript/src/classes/Undefined.pir
==============================================================================
--- (empty file)
+++ trunk/languages/ecmascript/src/classes/Undefined.pir Wed Dec 24 00:09:24 2008
@@ -0,0 +1,90 @@
+## $Id: Nil.pir 33898 2008-12-14 19:56:12Z pmichaud $
+
+=head1 NAME
+
+src/classes/Nil.pir - Nil objects
+
+=head1 DESCRIPTION
+
+=cut
+
+.namespace []
+
+.sub '' :anon :load :init
+ .local pmc jsmeta, nilproto
+ jsmeta = get_hll_global ['JSObject'], '$!JSMETA'
+ nilproto = jsmeta.'new_class'('Nil', 'parent'=>'Failure')
+ $P0 = nilproto.'new'()
+ set_hll_global ['Undefined'], 'undef', $P0
+ .end
+.end
+
+=head2 Methods
+
+=over
+
+=item 'list'
+
+=cut
+
+.namespace ['Nil']
+.sub 'list' :method
+ $P0 = new 'List'
+ .return ($P0)
+.end
+
+
+=item 'shift'
+
+=cut
+
+.namespace ['Nil']
+.sub 'shift' :method :vtable('shift_pmc')
+ .return (self)
+.end
+
+=back
+
+=head2 Coercion methods
+
+=over
+
+=item Scalar
+
+=cut
+
+.namespace ['Nil']
+.sub 'Scalar' :method
+ $P0 = new 'Failure'
+ .return ($P0)
+.end
+
+
+=back
+
+=head2 Private methods
+
+=over
+
+=item !flatten
+
+Return an empty list when flattened.
+
+=cut
+
+.namespace ['Nil']
+.sub '!flatten' :method
+ .tailcall self.'list'()
+.end
+
+
+=back
+
+=cut
+
+# Local Variables:
+# mode: pir
+# fill-column: 100
+# End:
+# vim: expandtab shiftwidth=4 ft=pir:
+
Modified: trunk/languages/ecmascript/src/parser/actions.pm
==============================================================================
--- trunk/languages/ecmascript/src/parser/actions.pm (original)
+++ trunk/languages/ecmascript/src/parser/actions.pm Wed Dec 24 00:09:24 2008
@@ -650,17 +650,21 @@
method true($/) {
# XXX change this into type a ECMAScript type, 'Boolean' or whatever
- make PAST::Val.new( :returns('Integer'), :value('1'), :node($/) );
+# make PAST::Val.new( :returns('Integer'), :value('1'), :node($/) );
+ make PAST::Var.new( :name(~$/), :namespace('JSBoolean'), :scope('package'), :node($/) );
+
}
method false($/) {
# XXX change this into type 'Boolean' or whatever
- make PAST::Val.new( :returns('Integer'), :value('0'), :node($/) );
+# make PAST::Val.new( :returns('Integer'), :value('0'), :node($/) );
+ make PAST::Var.new( :name(~$/), :namespace('JSBoolean'), :scope('package'), :node($/) );
}
method null($/) {
# XXX would this work?
make PAST::Var.new( :name('null'), :scope('package'), :node($/) );
+# make PAST::Var.new( :name(~$/), :namespace('Null'), :node($/) );
}
method object_literal($/) {
Modified: trunk/languages/ecmascript/src/parser/grammar.pg
==============================================================================
--- trunk/languages/ecmascript/src/parser/grammar.pg (original)
+++ trunk/languages/ecmascript/src/parser/grammar.pg Wed Dec 24 00:09:24 2008
@@ -441,8 +441,18 @@
# whitespace rule used implicity by rules
token ws {
- | <!ww> <ws_all>+
- | <ws_all>*
+ | <?{{ $P0 = get_global '$!ws'
+ if null $P0 goto noshort
+ $P1 = $P0.'to'()
+ $P2 = match.'to'()
+ if $P1 != $P2 goto noshort
+ .return (1)
+ noshort:
+ set_global '$!ws', match
+ .return (0)
+ }}>
+ | <!ww> <ws_all>+
+ | <ws_all>*
}
#### whitespace
@@ -597,8 +607,7 @@
}
rule call_expression {
- <member_expression> <arguments> <post_call_expr>*
- {*}
+ <member_expression> <arguments> <post_call_expr>* {*}
}
rule post_call_expr {
Added: trunk/languages/ecmascript/t/02-sanity-var.t
==============================================================================
--- (empty file)
+++ trunk/languages/ecmascript/t/02-sanity-var.t Wed Dec 24 00:09:24 2008
@@ -0,0 +1,10 @@
+print("1..1\n");
+var STATUS = "STATUS: ";
+print("#");
+print(STATUS);
+print("\n");
+print("ok 1\n");
+
+/*
+ * vim: ft=javascript:
+ */
Added: trunk/languages/ecmascript/t/03-boolean.t
==============================================================================
--- (empty file)
+++ trunk/languages/ecmascript/t/03-boolean.t Wed Dec 24 00:09:24 2008
@@ -0,0 +1,3 @@
+print(true);
+print(false);
+
-
[svn:parrot] r34320 - in trunk/languages/ecmascript: . config/makefiles src/builtin src/classes src/parser t
by tewk