Skip to content

Commit

Permalink
Use "method" atom to denote method properties
Browse files Browse the repository at this point in the history
Consider an ES6 object literal with a method that has empty arguments
and an empty body:

    {
      d() { }
    }

Before this commit, that would intuitively have been written as

    (object ('d ()))

which failed because the ('d ()) list has 2 elements, which the logic
attempted to compile to an ordinary property instead of a method. It's
ambiguous with

    {
      d: null
    }

if () were to compile to null.  It currently compiles to nothing (anko#32),
but the argument stands.

This change hence introduces this syntax

    (object (method 'd ()))

similarly to how getters and setters already allow empty bodies with

    (object (get 'd ())
            (set 'd ()))

I also moved the check for the initial "get" / "set" / "method" atom
above the args.length==2 check, to ensure it takes precedence.
  • Loading branch information
anko committed Jan 28, 2016
1 parent 4320a45 commit 98ddff3
Show file tree
Hide file tree
Showing 3 changed files with 31 additions and 22 deletions.
4 changes: 2 additions & 2 deletions doc/basics-reference.markdown
Original file line number Diff line number Diff line change
Expand Up @@ -339,7 +339,7 @@ implemented, though, so generator methods are not available.
(object
('prop)
((. Symbol 'toStringTag) "foo")
('method (arg) (return (+ arg 1)))
(method 'methodName (arg) (return (+ arg 1)))
(get data () (return 1)))

<!-- !test out object es6 -->
Expand All @@ -349,7 +349,7 @@ implemented, though, so generator methods are not available.
({
prop,
[Symbol.toStringTag]: 'foo',
method(arg) {
methodName(arg) {
return arg + 1;
},
get [data]() {
Expand Down
30 changes: 16 additions & 14 deletions src/built-in-macros.ls
Original file line number Diff line number Diff line change
Expand Up @@ -300,7 +300,22 @@ contents =
name : node.value
shorthand : true

| args.length is 2 =>
| is-atom args.0 and (args.0.value is \method) =>
compile-method.call this, args[1 til]

| is-atom args.0 and (args.0.value in <[ get set ]>) =>
compile-get-set.call this, args.0.value, args[1 til]

| args.0 `is-atom` \* =>
# TODO Implement
throw ObjectParamError "Unexpected '*' (generator methods not yet implemented)"

| otherwise # Assume a key-value pair for a normal object Property
if args.length isnt 2
throw Error "Not getter, setter, method, or shorthand property, \
but length is #{args.length} \
(expected 2: key and value)"

{node, computed} = maybe-unwrap-quote args.0

key = @compile node
Expand All @@ -313,19 +328,6 @@ contents =
key : key
value : @compile args.1

# Check this before compilation and macro resolution to ensure that
# neither can affect this, but that it can be avoided in the edge case if
# needed with `(id get)` or `(id set)`, where `(macro id (lambda (x) x))`.
| is-atom args.0 and (args.0.value in <[ get set ]>) =>
compile-get-set.call this, args.0.value, args[1 til]

# Reserve this for future generator use.
# TODO Implement
| args.0 `is-atom` \* =>
throw ObjectParamError "Unexpected '*' (generator methods not yet implemented)"

| otherwise => compile-method.call this, args

(...args) ->
type : \ObjectExpression
properties : args.map (arg, i) ~>
Expand Down
19 changes: 13 additions & 6 deletions test.ls
Original file line number Diff line number Diff line change
Expand Up @@ -745,11 +745,15 @@ test "object macro can create getters" ->
esl '(object (get \'a () (return 1)))'
..`@equals` '({\n get a() {\n return 1;\n }\n});'

test "object macro can create getters with empty body" ->
esl '(object (get \'a ()))'
..`@equals` '({\n get a() {\n }\n});'

test "object macro can create setters" ->
esl '(object (set \'a (x) (return 1)))'
..`@equals` '({\n set a(x) {\n return 1;\n }\n});'

test "object macro can create setters with no body" ->
test "object macro can create setters with empty body" ->
esl '(object (set y (x)))'
..`@equals` '({\n set [y](x) {\n }\n});'

Expand All @@ -767,9 +771,10 @@ test "object macro can create computed getters and setters" ->
test "object macro's parts can be ES6 methods" ->
esl '''
(object
('a () (return 1))
('b (x) (return (+ x 1)))
(c (x y) (return (+ x y 1))))
(method 'a () (return 1))
(method 'b (x) (return (+ x 1)))
(method c (x y) (return (+ x y 1)))
(method 'd ())) ; no args, empty method body
'''
..`@equals` """
({
Expand All @@ -781,6 +786,8 @@ test "object macro's parts can be ES6 methods" ->
},
[c](x, y) {
return x + (y + 1);
},
d() {
}
});
"""
Expand All @@ -804,10 +811,10 @@ test "object macro compiles complex ES6 object" ->
(set (. syms 'Sym) (value)
((. wm 'set) this value))
('printFoo ()
(method 'printFoo ()
((. console 'log) (. this 'foo)))
('concatFoo (value)
(method 'concatFoo (value)
(return (+ (. this 'foo) value))))
'''
..`@equals` '''
Expand Down

0 comments on commit 98ddff3

Please sign in to comment.