Skip to content

Commit a75ffd9

Browse files
author
uchida_t
committed
Argument is read-only with in default argument expressions.
jsx#327 (cherry picked from commit bbaabac) Failed to compile when `bin/jsx --minify t/run/400.constant-param- within-default-argument-expressions.jsx`. The minifier count reference to the original `ArgumentDeclaration`, and not clone but I think need replace `LocalVariable` within `LocalExpression` like `MemberFunctionDefinition#clone`.
1 parent 0173307 commit a75ffd9

5 files changed

+48
-6
lines changed

src/analysis.jsx

+24-4
Original file line numberDiff line numberDiff line change
@@ -229,8 +229,7 @@ class LocalVariable implements Stashable {
229229

230230
function touchVariable (context : AnalysisContext, token : Token, isAssignment : boolean) : boolean {
231231
if (isAssignment) {
232-
if (this._isConstant && context.getTopBlock().localVariableStatuses.getStatus(this) != LocalVariableStatuses.UNSET) {
233-
context.errors.push(new CompileError(token, "assignment of read-only variable"));
232+
if (!this.canAssignment(context, token)) {
234233
return false;
235234
}
236235
context.getTopBlock().localVariableStatuses.setStatus(this);
@@ -259,6 +258,15 @@ class LocalVariable implements Stashable {
259258
return true;
260259
}
261260

261+
function canAssignment (context : AnalysisContext, token : Token) : boolean {
262+
if (this._isConstant && context.getTopBlock().localVariableStatuses.getStatus(this) != LocalVariableStatuses.UNSET) {
263+
context.errors.push(new CompileError(token, "assignment of read-only variable"));
264+
return false;
265+
}
266+
return true;
267+
}
268+
269+
262270
override function toString () : string {
263271
return this._name.getValue() + " : " + this._type.toString();
264272
}
@@ -324,8 +332,13 @@ class ArgumentDeclaration extends LocalVariable {
324332
this._defaultValue = defaultValue;
325333
}
326334

335+
function constructor (name : Token, type : Type, isConst : boolean, defaultValue : Expression) {
336+
super(name, type, isConst);
337+
this._defaultValue = defaultValue;
338+
}
339+
327340
function clone () : ArgumentDeclaration {
328-
return new ArgumentDeclaration(this._name, this._type, Util.cloneNullable(this._defaultValue));
341+
return new ArgumentDeclaration(this._name, this._type, this._isConstant, Util.cloneNullable(this._defaultValue));
329342
}
330343

331344
function getDefaultValue() : Expression {
@@ -334,13 +347,20 @@ class ArgumentDeclaration extends LocalVariable {
334347

335348
override function _instantiate (instantiationContext : InstantiationContext) : ArgumentDeclaration {
336349
var type = this._type != null ? this._type.instantiate(instantiationContext, false) : null;
337-
return new ArgumentDeclaration(this._name, type, this._defaultValue);
350+
return new ArgumentDeclaration(this._name, type, this._isConstant, this._defaultValue);
338351
}
339352

340353
override function instantiateAndPush (instantiationContext : InstantiationContext) : ArgumentDeclaration {
341354
return super.instantiateAndPush(instantiationContext) as ArgumentDeclaration;
342355
}
343356

357+
override function canAssignment (context : AnalysisContext, token : Token) : boolean {
358+
if (this._isConstant) {
359+
context.errors.push(new CompileError(token, "The preceding argument is read-only within the default argument expression"));
360+
return false;
361+
}
362+
return true;
363+
}
344364
}
345365

346366
class LocalVariableStatuses {

src/classdef.jsx

+1-1
Original file line numberDiff line numberDiff line change
@@ -1698,7 +1698,7 @@ class MemberFunctionDefinition extends MemberDefinition implements Block {
16981698
for (; origArgIndex != this.getArguments().length; ++origArgIndex) {
16991699
// build list of formal args (of the generated function)
17001700
var formalArgs = this.getArguments().slice(0, origArgIndex).map.<ArgumentDeclaration>((arg) -> {
1701-
return new ArgumentDeclaration(arg.getName(), arg.getType());
1701+
return new ArgumentDeclaration(arg.getName(), arg.getType(), true, null);
17021702
});
17031703
// build function body
17041704
var argExprs = formalArgs.map.<Expression>((arg) -> {

src/parser.jsx

+1-1
Original file line numberDiff line numberDiff line change
@@ -3447,7 +3447,7 @@ class Parser {
34473447
var assignToken = this._expectOpt("=");
34483448
if (assignToken != null) {
34493449
var state = this._preserveState();
3450-
this._pushScope(null, args);
3450+
this._pushScope(null, args.map(arg => new ArgumentDeclaration(arg.getName(), arg.getType(), true, arg.getDefaultValue())));
34513451
try {
34523452
if ((defaultValue = this._assignExpr(true)) == null) {
34533453
return null;
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
class C {
2+
3+
function fn(a : number, b : number = ++a) : void {
4+
}
5+
6+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
/*EXPECTED
2+
1
3+
1
4+
*/
5+
class _Main {
6+
7+
static function fn(a : number, b : () => number = () => a) : void {
8+
log b();
9+
a = 10;
10+
log b();
11+
}
12+
13+
static function main(args : string[]) : void {
14+
_Main.fn(1);
15+
}
16+
}

0 commit comments

Comments
 (0)