Skip to content
This repository
Browse code

Back to naked constructors.

  • Loading branch information...
commit 2aedbc2e42cc782e3e6f6b396dc04819ef790ae6 1 parent f0b73dc
Jeremy Ashkenas authored November 13, 2010
2  documentation/coffee/classes.coffee
... ...
@@ -1,5 +1,5 @@
1 1
 class Animal
2  
-  constructor: (@name) ->
  2
+  (@name) ->
3 3
 
4 4
   move: (meters) ->
5 5
     alert @name + " moved " + meters + "m."
2  examples/code.coffee
@@ -135,7 +135,7 @@ aliquam erat volutpat. Ut wisi enim ad."
135 135
 
136 136
 # Inheritance and calling super.
137 137
 class Animal
138  
-  constructor: (@name) ->
  138
+  (@name) ->
139 139
 
140 140
   move: (meters) ->
141 141
     alert this.name + " moved " + meters + "m."
2  examples/computer_science/linked_list.coffee
... ...
@@ -1,7 +1,7 @@
1 1
 # "Classic" linked list implementation that doesn't keep track of its size.
2 2
 class LinkedList
3 3
 
4  
-  constructor: ->
  4
+  ->
5 5
     this._head = null # Pointer to the first item in the list.
6 6
 
7 7
 
2  examples/potion.coffee
@@ -71,7 +71,7 @@ print p.name
71 71
 # Policeman ('Constable') print
72 72
 
73 73
 class Policeman extends Person
74  
-  constructor: (@rank) ->
  74
+  (@rank) ->
75 75
 
76 76
   print: ->
77 77
     print 'My name is ' + @name + " and I'm a " + @rank + '.'
34  lib/nodes.js
@@ -851,25 +851,10 @@
851 851
             base = assign.variable.base;
852 852
             delete assign.context;
853 853
             func = assign.value;
854  
-            if (base.value === 'constructor') {
855  
-              if (ctor) {
856  
-                throw new Error('cannot define more than one constructor in a class');
857  
-              }
858  
-              if (func.bound) {
859  
-                throw new Error('cannot define a constructor as a bound function');
860  
-              }
861  
-              if (func instanceof Code) {
862  
-                ctor = func;
863  
-              } else {
864  
-                ctor = new Assign(new Value(lname), func);
865  
-              }
866  
-              assign = null;
867  
-            } else {
868  
-              assign.variable = new Value(lname, [new Accessor(base, 'proto')]);
869  
-              if (func instanceof Code && func.bound) {
870  
-                boundFuncs.push(base);
871  
-                func.bound = false;
872  
-              }
  854
+            assign.variable = new Value(lname, [new Accessor(base, 'proto')]);
  855
+            if (func instanceof Code && func.bound) {
  856
+              boundFuncs.push(base);
  857
+              func.bound = false;
873 858
             }
874 859
           }
875 860
           _results.push(assign);
@@ -883,6 +868,15 @@
883 868
         node = _ref[i];
884 869
         if (node instanceof Value && node.isObject(true)) {
885 870
           exps[i] = compact(convert(node));
  871
+        } else if (node instanceof Code) {
  872
+          if (ctor) {
  873
+            throw new Error('cannot define more than one constructor in a class');
  874
+          }
  875
+          if (node.bound) {
  876
+            throw new Error('cannot define a constructor as a bound function');
  877
+          }
  878
+          ctor = node;
  879
+          exps[i] = null;
886 880
         } else {
887 881
           others.push(node);
888 882
         }
@@ -906,7 +900,7 @@
906 900
         other = others[_i];
907 901
         _fn(other);
908 902
       }
909  
-      this.body.expressions = exps = flatten(exps);
  903
+      this.body.expressions = exps = compact(flatten(exps));
910 904
       if (!ctor) {
911 905
         ctor = new Code;
912 906
         if (this.parent) {
80  src/nodes.coffee
@@ -157,7 +157,7 @@ exports.Expressions = class Expressions extends Base
157 157
 
158 158
   children: ['expressions']
159 159
 
160  
-  constructor: (nodes) ->
  160
+  (nodes) ->
161 161
     @expressions = compact flatten nodes or []
162 162
 
163 163
   # Tack an expression on to the end of this expression list.
@@ -257,7 +257,7 @@ exports.Expressions = class Expressions extends Base
257 257
 # `true`, `false`, `null`...
258 258
 exports.Literal = class Literal extends Base
259 259
 
260  
-  constructor: (@value) ->
  260
+  (@value) ->
261 261
 
262 262
   makeReturn: ->
263 263
     if @isPureStatement() then this else new Return this
@@ -292,7 +292,7 @@ exports.Return = class Return extends Base
292 292
   isStatement    : YES
293 293
   isPureStatement: YES
294 294
 
295  
-  constructor: (@expression) ->
  295
+  (@expression) ->
296 296
 
297 297
   makeReturn: THIS
298 298
 
@@ -313,7 +313,7 @@ exports.Value = class Value extends Base
313 313
   children: ['base', 'properties']
314 314
 
315 315
   # A **Value** has a base and a list of property accesses.
316  
-  constructor: (base, props, tag) ->
  316
+  (base, props, tag) ->
317 317
     return base if not props and base instanceof Value
318 318
     @base       = base
319 319
     @properties = props or []
@@ -404,7 +404,7 @@ exports.Value = class Value extends Base
404 404
 # at the same position.
405 405
 exports.Comment = class Comment extends Base
406 406
 
407  
-  constructor: (@comment) ->
  407
+  (@comment) ->
408 408
 
409 409
   isPureStatement: YES
410 410
   isStatement:     YES
@@ -423,7 +423,7 @@ exports.Call = class Call extends Base
423 423
 
424 424
   children: ['variable', 'args']
425 425
 
426  
-  constructor: (variable, @args = [], @soak) ->
  426
+  (variable, @args = [], @soak) ->
427 427
     @isNew    = false
428 428
     @isSuper  = variable is 'super'
429 429
     @variable = if @isSuper then null else variable
@@ -526,7 +526,7 @@ exports.Extends = class Extends extends Base
526 526
 
527 527
   children: ['child', 'parent']
528 528
 
529  
-  constructor: (@child, @parent) ->
  529
+  (@child, @parent) ->
530 530
 
531 531
   # Hooks one constructor into another's prototype chain.
532 532
   compile: (o) ->
@@ -541,7 +541,7 @@ exports.Accessor = class Accessor extends Base
541 541
 
542 542
   children: ['name']
543 543
 
544  
-  constructor: (@name, tag) ->
  544
+  (@name, tag) ->
545 545
     @proto = if tag is 'proto' then '.prototype' else ''
546 546
     @soak  = tag is 'soak'
547 547
 
@@ -558,7 +558,7 @@ exports.Index = class Index extends Base
558 558
 
559 559
   children: ['index']
560 560
 
561  
-  constructor: (@index) ->
  561
+  (@index) ->
562 562
 
563 563
   compile: (o) ->
564 564
     (if @proto then '.prototype' else '') + "[#{ @index.compile o, LEVEL_PAREN }]"
@@ -573,7 +573,7 @@ exports.Obj = class Obj extends Base
573 573
 
574 574
   children: ['properties']
575 575
 
576  
-  constructor: (props, @generated = false) ->
  576
+  (props, @generated = false) ->
577 577
     @objects = @properties = props or []
578 578
 
579 579
   compileNode: (o) ->
@@ -637,7 +637,7 @@ exports.Arr = class Arr extends Base
637 637
 
638 638
   children: ['objects']
639 639
 
640  
-  constructor: (objs) ->
  640
+  (objs) ->
641 641
     @objects = objs or []
642 642
 
643 643
   compileNode: (o) ->
@@ -664,7 +664,7 @@ exports.Class = class Class extends Base
664 664
 
665 665
   # Initialize a **Class** with its name, an optional superclass, and a
666 666
   # list of prototype property assignments.
667  
-  constructor: (@variable, @parent, @body = new Expressions) ->
  667
+  (@variable, @parent, @body = new Expressions) ->
668 668
 
669 669
   # Instead of generating the JavaScript string directly, we build up the
670 670
   # equivalent syntax tree and compile that, in pieces. You can see the
@@ -695,21 +695,10 @@ exports.Class = class Class extends Base
695 695
           base = assign.variable.base
696 696
           delete assign.context
697 697
           func = assign.value
698  
-          if base.value is 'constructor'
699  
-            if ctor
700  
-              throw new Error 'cannot define more than one constructor in a class'
701  
-            if func.bound
702  
-              throw new Error 'cannot define a constructor as a bound function'
703  
-            if func instanceof Code
704  
-              ctor = func
705  
-            else
706  
-              ctor = new Assign(new Value(lname), func)
707  
-            assign = null
708  
-          else
709  
-            assign.variable = new Value(lname, [new Accessor(base, 'proto')])
710  
-            if func instanceof Code and func.bound
711  
-              boundFuncs.push base
712  
-              func.bound = no
  698
+          assign.variable = new Value(lname, [new Accessor(base, 'proto')])
  699
+          if func instanceof Code and func.bound
  700
+            boundFuncs.push base
  701
+            func.bound = no
713 702
         assign
714 703
 
715 704
     boundFuncs = []
@@ -717,6 +706,13 @@ exports.Class = class Class extends Base
717 706
     for node, i in exps = @body.expressions
718 707
       if node instanceof Value and node.isObject(true)
719 708
         exps[i] = compact convert node
  709
+      else if node instanceof Code
  710
+        if ctor
  711
+          throw new Error 'cannot define more than one constructor in a class'
  712
+        if node.bound
  713
+          throw new Error 'cannot define a constructor as a bound function'
  714
+        ctor = node
  715
+        exps[i] = null
720 716
       else
721 717
         others.push node
722 718
 
@@ -729,7 +725,7 @@ exports.Class = class Class extends Base
729 725
               n2.expressions[j] = compact convert expr2
730 726
           n2.expressions = flatten n2.expressions
731 727
 
732  
-    @body.expressions = exps = flatten exps
  728
+    @body.expressions = exps = compact flatten exps
733 729
     unless ctor
734 730
       ctor = new Code
735 731
       if @parent
@@ -762,7 +758,7 @@ exports.Assign = class Assign extends Base
762 758
 
763 759
   children: ['variable', 'value']
764 760
 
765  
-  constructor: (@variable, @value, @context) ->
  761
+  (@variable, @value, @context) ->
766 762
 
767 763
   assigns: (name) ->
768 764
     @[if @context is 'object' then 'value' else 'variable'].assigns name
@@ -877,7 +873,7 @@ exports.Code = class Code extends Base
877 873
 
878 874
   children: ['params', 'body']
879 875
 
880  
-  constructor: (params, body, tag) ->
  876
+  (params, body, tag) ->
881 877
     @params  = params or []
882 878
     @body    = body or new Expressions
883 879
     @bound   = tag is 'boundfunc'
@@ -944,7 +940,7 @@ exports.Param = class Param extends Base
944 940
 
945 941
   children: ['name', 'value']
946 942
 
947  
-  constructor: (@name, @value, @splat) ->
  943
+  (@name, @value, @splat) ->
948 944
 
949 945
   compile: (o) ->
950 946
     @name.compile o, LEVEL_LIST
@@ -969,7 +965,7 @@ exports.Splat = class Splat extends Base
969 965
 
970 966
   isAssignable: YES
971 967
 
972  
-  constructor: (name) ->
  968
+  (name) ->
973 969
     @name = if name.compile then name else new Literal name
974 970
 
975 971
   assigns: (name) ->
@@ -1009,7 +1005,7 @@ exports.While = class While extends Base
1009 1005
 
1010 1006
   isStatement: YES
1011 1007
 
1012  
-  constructor: (condition, options) ->
  1008
+  (condition, options) ->
1013 1009
     @condition = if options?.invert then condition.invert() else condition
1014 1010
     @guard     = options?.guard
1015 1011
 
@@ -1073,7 +1069,7 @@ exports.Op = class Op extends Base
1073 1069
 
1074 1070
   children: ['first', 'second']
1075 1071
 
1076  
-  constructor: (op, first, second, flip) ->
  1072
+  (op, first, second, flip) ->
1077 1073
     return new In first, second if op is 'in'
1078 1074
     if op is 'new'
1079 1075
       return first.newInstance() if first instanceof Call
@@ -1150,7 +1146,7 @@ exports.In = class In extends Base
1150 1146
 
1151 1147
   invert: NEGATE
1152 1148
 
1153  
-  constructor: (@object, @array) ->
  1149
+  (@object, @array) ->
1154 1150
 
1155 1151
   compileNode: (o) ->
1156 1152
     if @array instanceof Value and @array.isArray()
@@ -1186,7 +1182,7 @@ exports.Try = class Try extends Base
1186 1182
 
1187 1183
   isStatement: YES
1188 1184
 
1189  
-  constructor: (@attempt, @error, @recovery, @ensure) ->
  1185
+  (@attempt, @error, @recovery, @ensure) ->
1190 1186
 
1191 1187
   makeReturn: ->
1192 1188
     @attempt  = @attempt .makeReturn() if @attempt
@@ -1217,7 +1213,7 @@ exports.Throw = class Throw extends Base
1217 1213
 
1218 1214
   isStatement: YES
1219 1215
 
1220  
-  constructor: (@expression) ->
  1216
+  (@expression) ->
1221 1217
 
1222 1218
   # A **Throw** is already a return, of sorts...
1223 1219
   makeReturn: THIS
@@ -1236,7 +1232,7 @@ exports.Existence = class Existence extends Base
1236 1232
 
1237 1233
   invert: NEGATE
1238 1234
 
1239  
-  constructor: (@expression) ->
  1235
+  (@expression) ->
1240 1236
 
1241 1237
   compileNode: (o) ->
1242 1238
     code = @expression.compile o, LEVEL_OP
@@ -1261,7 +1257,7 @@ exports.Parens = class Parens extends Base
1261 1257
 
1262 1258
   children: ['expression']
1263 1259
 
1264  
-  constructor: (@expression) ->
  1260
+  (@expression) ->
1265 1261
 
1266 1262
   unwrap    : -> @expression
1267 1263
   isComplex : -> @expression.isComplex()
@@ -1291,7 +1287,7 @@ exports.For = class For extends Base
1291 1287
 
1292 1288
   isStatement: YES
1293 1289
 
1294  
-  constructor: (body, head) ->
  1290
+  (body, head) ->
1295 1291
     if head.index instanceof Value
1296 1292
       throw SyntaxError 'index cannot be a pattern matching expression'
1297 1293
     extend this, head
@@ -1425,7 +1421,7 @@ exports.Switch = class Switch extends Base
1425 1421
 
1426 1422
   isStatement: YES
1427 1423
 
1428  
-  constructor: (@subject, @cases, @otherwise) ->
  1424
+  (@subject, @cases, @otherwise) ->
1429 1425
 
1430 1426
   makeReturn: ->
1431 1427
     pair[1].makeReturn() for pair in @cases
@@ -1459,7 +1455,7 @@ exports.If = class If extends Base
1459 1455
 
1460 1456
   children: ['condition', 'body', 'elseBody']
1461 1457
 
1462  
-  constructor: (condition, @body, options = {}) ->
  1458
+  (condition, @body, options = {}) ->
1463 1459
     @condition = if options.invert then condition.invert() else condition
1464 1460
     @elseBody  = null
1465 1461
     @isChain   = false
2  src/optparse.coffee
@@ -13,7 +13,7 @@ exports.OptionParser = class OptionParser
13 13
   #     [short-flag, long-flag, description]
14 14
   #
15 15
   # Along with an an optional banner for the usage help.
16  
-  constructor: (rules, @banner) ->
  16
+  (rules, @banner) ->
17 17
     @rules = buildRules rules
18 18
 
19 19
   # Parse the list of arguments, populating an `options` object with all of the
2  src/scope.coffee
@@ -17,7 +17,7 @@ exports.Scope = class Scope
17 17
   # as well as a reference to the **Expressions** node is belongs to, which is
18 18
   # where it should declare its variables, and a reference to the function that
19 19
   # it wraps.
20  
-  constructor: (@parent, @expressions, @method) ->
  20
+  (@parent, @expressions, @method) ->
21 21
     @variables = [{name: 'arguments', type: 'arguments'}]
22 22
     @positions = {}
23 23
     if @parent
2  test/test_arguments.coffee
@@ -35,7 +35,7 @@ eq context.arg, 3
35 35
 eq context.arg.join(' '), '1 2 3'
36 36
 
37 37
 class Klass
38  
-  constructor: (@one, @two) ->
  38
+  (@one, @two) ->
39 39
 
40 40
 obj = new Klass 1, 2
41 41
 
24  test/test_classes.coffee
@@ -18,7 +18,7 @@ thirdCtor = ->
18 18
   @array = [1, 2, 3]
19 19
 
20 20
 class ThirdChild extends SecondChild
21  
-  constructor: -> thirdCtor.call this
  21
+  -> thirdCtor.call this
22 22
 
23 23
   # Gratuitous comment for testing.
24 24
   func: (string) ->
@@ -40,15 +40,15 @@ ok (new ThirdChild).array.join(' ') is '1 2 3'
40 40
 
41 41
 
42 42
 class TopClass
43  
-  constructor: (arg) ->
  43
+  (arg) ->
44 44
     @prop = 'top-' + arg
45 45
 
46 46
 class SuperClass extends TopClass
47  
-  constructor: (arg) ->
  47
+  (arg) ->
48 48
     super 'super-' + arg
49 49
 
50 50
 class SubClass extends SuperClass
51  
-  constructor: ->
  51
+  ->
52 52
     super 'sub'
53 53
 
54 54
 ok (new SubClass).prop is 'top-super-sub'
@@ -57,7 +57,7 @@ ok (new SubClass).prop is 'top-super-sub'
57 57
 class OneClass
58 58
   @new = 'new'
59 59
   function: 'function'
60  
-  constructor: (name) -> @name = name
  60
+  (name) -> @name = name
61 61
 
62 62
 class TwoClass extends OneClass
63 63
 delete TwoClass.new
@@ -131,10 +131,10 @@ ok obj.amI()
131 131
 
132 132
 # super() calls in constructors of classes that are defined as object properties.
133 133
 class Hive
134  
-  constructor: (name) -> @name = name
  134
+  (name) -> @name = name
135 135
 
136 136
 class Hive.Bee extends Hive
137  
-  constructor: (name) -> super
  137
+  (name) -> super
138 138
 
139 139
 maya = new Hive.Bee 'Maya'
140 140
 ok maya.name is 'Maya'
@@ -154,7 +154,7 @@ ok instance.name() is 'class'
154 154
 # ... or statically, to the class.
155 155
 class Dog
156 156
 
157  
-  constructor: (name) ->
  157
+  (name) ->
158 158
     @name = name
159 159
 
160 160
   bark: =>
@@ -188,7 +188,7 @@ eq (func() for func in m.generate()).join(' '), '10 10 10'
188 188
 
189 189
 # Testing a contructor called with varargs.
190 190
 class Connection
191  
-  constructor: (one, two, three) ->
  191
+  (one, two, three) ->
192 192
     [@one, @two, @three] = [one, two, three]
193 193
 
194 194
   out: ->
@@ -281,10 +281,12 @@ classMaker = ->
281 281
     @value = inner
282 282
 
283 283
 class One
284  
-  constructor: classMaker()
  284
+  ctor = classMaker()
  285
+  -> ctor.call this
285 286
 
286 287
 class Two
287  
-  constructor: classMaker()
  288
+  ctor = classMaker()
  289
+  -> ctor.call this
288 290
 
289 291
 ok (new One).value is 1
290 292
 ok (new Two).value is 2
2  test/test_comprehensions.coffee
@@ -146,7 +146,7 @@ ok expr(2, 4, 8).join(' ') is '4 16 64'
146 146
 
147 147
 # Fast object comprehensions over all properties, including prototypal ones.
148 148
 class Cat
149  
-  constructor: -> @name = 'Whiskers'
  149
+  -> @name = 'Whiskers'
150 150
   breed: 'tabby'
151 151
   hair:  'cream'
152 152
 
2  test/test_existence.coffee
@@ -81,7 +81,7 @@ eq ident(non?.existent().method()), undefined, 'soaks inner values'
81 81
 # Soaks constructor invocations.
82 82
 a = 0
83 83
 class Foo
84  
-  constructor: -> a += 1
  84
+  -> a += 1
85 85
   bar: "bat"
86 86
 
87 87
 ok (new Foo())?.bar is 'bat'

0 notes on commit 2aedbc2

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