@@ -59,6 +59,7 @@ void functionCodegen (Ref<AstNode> statement, CodegenState* pState);
59
59
void assignmentCodegen (Ref<AstNode> statement, CodegenState* pState);
60
60
void fncallCodegen (Ref<AstNode> statement, CodegenState* pState);
61
61
void thisCallCodegen (Ref<AstNode> statement, CodegenState* pState);
62
+ void constructorCodegen (Ref<AstNode> statement, CodegenState* pState);
62
63
void literalCodegen (Ref<AstNode> statement, CodegenState* pState);
63
64
void identifierCodegen (Ref<AstNode> statement, CodegenState* pState);
64
65
void arrayCodegen (Ref<AstNode> statement, CodegenState* pState);
@@ -450,34 +451,31 @@ void assignmentCodegen (Ref<AstNode> statement, CodegenState* pState)
450
451
void fncallCodegen (Ref<AstNode> statement, CodegenState* pState)
451
452
{
452
453
if (statement->getType () == AST_NEWCALL)
453
- {
454
- // Create a new object, and pass it as 'this' reference.
455
- callCodegen (" @newObj" , 0 , pState);
456
- }
454
+ constructorCodegen (statement, pState);
457
455
else
458
456
{
459
457
const AstNodeTypes fnExprType = statement->children ()[0 ]->getType ();
460
458
461
459
// If the expression to get the function reference is an object member access,
462
460
// then use generate a 'this' call.
463
461
if (fnExprType == AST_MEMBER_ACCESS || fnExprType == AST_ARRAY_ACCESS)
464
- {
465
462
thisCallCodegen (statement, pState);
466
- return ;
467
- }
468
463
else
464
+ {
465
+ // Regular function call (no this pointer)
469
466
pushUndefined (pState); // No 'this' pointer.
470
- }
471
-
472
- // Parameters evaluation
473
- const int nChilds = (int )statement->children ().size ();
474
- for (int i = 1 ; i < nChilds; ++i)
475
- childCodegen (statement, i, pState);
467
+
468
+ // Parameters evaluation
469
+ const int nChilds = (int )statement->children ().size ();
470
+ for (int i = 1 ; i < nChilds; ++i)
471
+ childCodegen (statement, i, pState);
476
472
477
- // Evaluate function reference expression
478
- childCodegen (statement, 0 , pState);
479
-
480
- callInstruction (nChilds, pState);
473
+ // Evaluate function reference expression
474
+ childCodegen (statement, 0 , pState);
475
+
476
+ callInstruction (nChilds, pState);
477
+ }
478
+ }
481
479
}
482
480
483
481
/* *
@@ -508,6 +506,41 @@ void thisCallCodegen (Ref<AstNode> statement, CodegenState* pState)
508
506
callInstruction (nChilds, pState);
509
507
}
510
508
509
+ /* *
510
+ * Generates code for a operator 'new' function call
511
+ * @param statement
512
+ * @param pState
513
+ */
514
+ void constructorCodegen (Ref<AstNode> statement, CodegenState* pState)
515
+ {
516
+ childCodegen (statement, 0 , pState); // [function]
517
+ instruction8 (OC_CP, pState); // [function, function]
518
+
519
+ // Create a new object, to pass it as 'this' reference. '@newObj' receives as
520
+ // parameter the constructor function, from which it will read the object prototype.
521
+ callCodegen (" @newObj" , 1 , pState); // [function, this]
522
+
523
+ instruction8 (OC_SWAP, pState); // [this, function]
524
+ instruction8 (OC_CP+1 , pState); // [this, function, this]
525
+ instruction8 (OC_SWAP, pState); // [this, this, function]
526
+
527
+ // Parameters evaluation
528
+ const int nChilds = (int )statement->children ().size ();
529
+ for (int i = 1 ; i < nChilds; ++i)
530
+ {
531
+ childCodegen (statement, i, pState); // Parameter evaluation
532
+ instruction8 (OC_SWAP, pState); // Put function back on top
533
+ }
534
+
535
+ // stack: [this, this, param1, param2,... paramN, function]
536
+
537
+ // Write call instruction
538
+ callInstruction (nChilds, pState); // [this, result]
539
+
540
+ // Discard function result, keep 'this' (the new object)
541
+ instruction8 (OC_POP, pState);
542
+ }
543
+
511
544
/* *
512
545
* Generates code for a literal expression.
513
546
* @param statement
0 commit comments