initial draft of return, break, and show
This commit is contained in:
Родитель
e0a1be0007
Коммит
6d1b18393d
98
ast/ast.ts
98
ast/ast.ts
|
@ -131,6 +131,7 @@ module TDev.AST {
|
|||
private stableVersions : string[];
|
||||
public tutorialWarning: string;
|
||||
public _hint:string;
|
||||
public _compilerBreakLabel:any;
|
||||
|
||||
constructor() {
|
||||
super()
|
||||
|
@ -678,6 +679,97 @@ module TDev.AST {
|
|||
public forSearch() { return "for do " + this.upperBound.forSearch(); }
|
||||
}
|
||||
|
||||
export class Return
|
||||
extends Stmt
|
||||
{
|
||||
public expr:ExprHolder;
|
||||
public retLocal:LocalDef;
|
||||
public action:Stmt;
|
||||
|
||||
constructor() {
|
||||
super()
|
||||
}
|
||||
public nodeType() { return "return"; }
|
||||
public calcNode() { return this.expr; }
|
||||
public accept(v:NodeVisitor) { return v.visitReturn(this); }
|
||||
public isExecutableStmt() { return true; }
|
||||
public allowSimplify() { return true }
|
||||
|
||||
public writeTo(tw:TokenWriter)
|
||||
{
|
||||
this.writeIdOpt(tw);
|
||||
tw.keyword("return").node(this.expr);
|
||||
tw.op0(";").nl();
|
||||
}
|
||||
|
||||
private parseFrom(p:Parser)
|
||||
{
|
||||
this.setStableName(p.consumeLabel());
|
||||
this.expr = p.parseExpr();
|
||||
p.skipOp(";")
|
||||
}
|
||||
|
||||
public forSearch() { return "return " + this.expr.forSearch(); }
|
||||
}
|
||||
|
||||
export class Show
|
||||
extends Stmt
|
||||
{
|
||||
public expr:ExprHolder;
|
||||
public postCall:Expr;
|
||||
|
||||
constructor() {
|
||||
super()
|
||||
}
|
||||
public nodeType() { return "show"; }
|
||||
public calcNode() { return this.expr; }
|
||||
public accept(v:NodeVisitor) { return v.visitShow(this); }
|
||||
public isExecutableStmt() { return true; }
|
||||
public allowSimplify() { return true }
|
||||
|
||||
public writeTo(tw:TokenWriter)
|
||||
{
|
||||
this.writeIdOpt(tw);
|
||||
tw.keyword("do").id("show").node(this.expr);
|
||||
tw.op0(";").nl();
|
||||
}
|
||||
|
||||
private parseFrom(p:Parser)
|
||||
{
|
||||
this.setStableName(p.consumeLabel());
|
||||
this.expr = p.parseExpr();
|
||||
p.skipOp(";")
|
||||
}
|
||||
|
||||
public forSearch() { return "show " + this.expr.forSearch(); }
|
||||
}
|
||||
|
||||
export class Break
|
||||
extends Stmt
|
||||
{
|
||||
constructor() {
|
||||
super()
|
||||
}
|
||||
public loop:Stmt;
|
||||
public nodeType() { return "break"; }
|
||||
public accept(v:NodeVisitor) { return v.visitBreak(this); }
|
||||
public isExecutableStmt() { return true; }
|
||||
|
||||
public writeTo(tw:TokenWriter)
|
||||
{
|
||||
this.writeIdOpt(tw);
|
||||
tw.keyword("break").op0(";").nl();
|
||||
}
|
||||
|
||||
private parseFrom(p:Parser)
|
||||
{
|
||||
this.setStableName(p.consumeLabel());
|
||||
p.skipOp(";")
|
||||
}
|
||||
|
||||
public forSearch() { return "break"; }
|
||||
}
|
||||
|
||||
export class Foreach
|
||||
extends Stmt
|
||||
{
|
||||
|
@ -3725,6 +3817,9 @@ module TDev.AST {
|
|||
public visitForeach(n:Foreach) { return this.visitStmt(n); }
|
||||
public visitWhile(n:While) { return this.visitStmt(n); }
|
||||
public visitBox(n:Box) { return this.visitStmt(n); }
|
||||
public visitShow(n:Show) { return this.visitStmt(n); }
|
||||
public visitBreak(n:Break) { return this.visitStmt(n); }
|
||||
public visitReturn(n:Return) { return this.visitStmt(n); }
|
||||
public visitAnyIf(n:If) { return this.visitStmt(n); }
|
||||
public visitIf(n:If) { return this.visitAnyIf(n); }
|
||||
public visitElseIf(n:If) { return this.visitAnyIf(n); }
|
||||
|
@ -5138,6 +5233,9 @@ module TDev.AST {
|
|||
public visitInlineActions(n:InlineActions) { this.visitChStmt(n); }
|
||||
public visitActionHeader(n:ActionHeader) { this.visitChStmt(n); }
|
||||
public visitExprStmt(n:ExprStmt) { this.visitChStmt(n); }
|
||||
public visitBreak(n:Break) { this.visitChStmt(n); }
|
||||
public visitReturn(n:Return) { this.visitChStmt(n); }
|
||||
public visitShow(n:Show) { this.visitChStmt(n); }
|
||||
|
||||
public visitActionParameter(n:ActionParameter) { this.withBoundLocal(n, n.local) }
|
||||
|
||||
|
|
|
@ -885,6 +885,7 @@ module TDev.AST
|
|||
this.updateAnalysisInfo(w.calcNode());
|
||||
this.markLocation(w);
|
||||
var begLabel = this.allocateLabel();
|
||||
w._compilerBreakLabel = this.allocateLabel()
|
||||
this.aux.push(begLabel);
|
||||
var cond = this.topExpr(w.condition, w);
|
||||
this.resetAnalysisInfo();
|
||||
|
@ -895,9 +896,47 @@ module TDev.AST
|
|||
ifNode.thenBody.push(JsGoto.simple(begLabel));
|
||||
ifNode.elseBody = [];
|
||||
res.push(ifNode);
|
||||
res.push(w._compilerBreakLabel)
|
||||
return res;
|
||||
}
|
||||
|
||||
public visitBreak(b:Break)
|
||||
{
|
||||
this.markLocation(b);
|
||||
var res = this.flushAux();
|
||||
if (b.loop)
|
||||
res.push(JsGoto.simple(b.loop._compilerBreakLabel))
|
||||
this.resetAnalysisInfo();
|
||||
return res
|
||||
}
|
||||
|
||||
public visitReturn(r:Return)
|
||||
{
|
||||
this.markLocation(r);
|
||||
if (r.retLocal) {
|
||||
this.updateAnalysisInfo(r.expr);
|
||||
var val = this.topExpr(r.expr, r);
|
||||
this.resetAnalysisInfo();
|
||||
}
|
||||
var res = this.flushAux();
|
||||
if (r.retLocal)
|
||||
res.push(this.localVarRef(r.retLocal).gets(val))
|
||||
res.push(JsGoto.simple(r.action._compilerBreakLabel))
|
||||
return res
|
||||
}
|
||||
|
||||
public visitShow(s:Show)
|
||||
{
|
||||
this.markLocation(s);
|
||||
this.updateAnalysisInfo(s.expr);
|
||||
var ex = this.doExpr(s.postCall)
|
||||
var r = this.flushAux();
|
||||
if (ex != this.unit)
|
||||
r.push(new JsExprStmt(ex));
|
||||
this.resetAnalysisInfo();
|
||||
return s
|
||||
}
|
||||
|
||||
private compileInlineAction(inl:InlineAction)
|
||||
{
|
||||
var a = new Action();
|
||||
|
@ -982,6 +1021,7 @@ module TDev.AST
|
|||
collTmp = this.newTmpVar("coll", this.topExpr(f.collection, f));
|
||||
}
|
||||
this.resetAnalysisInfo();
|
||||
f._compilerBreakLabel = this.allocateLabel()
|
||||
|
||||
var idxTmp = this.newTmpVarOK("idx", this.term("0"));
|
||||
var begLabel = this.allocateLabel();
|
||||
|
@ -1028,6 +1068,7 @@ module TDev.AST
|
|||
ifNode.thenBody.push(JsGoto.simple(begLabel));
|
||||
ifNode.elseBody = [];
|
||||
res.push(ifNode);
|
||||
res.push(f._compilerBreakLabel);
|
||||
return res;
|
||||
}
|
||||
|
||||
|
@ -1040,6 +1081,7 @@ module TDev.AST
|
|||
var idx = this.localVarRef(f.boundLocal);
|
||||
this.aux.push(idx.gets(this.term("0")));
|
||||
var begLabel = this.allocateLabel();
|
||||
f._compilerBreakLabel = this.allocateLabel()
|
||||
var res = this.flushAux();
|
||||
res.push(begLabel);
|
||||
var ifNode = this.allocateIf();
|
||||
|
@ -1049,6 +1091,7 @@ module TDev.AST
|
|||
ifNode.thenBody.push(JsGoto.simple(begLabel));
|
||||
ifNode.elseBody = [];
|
||||
res.push(ifNode);
|
||||
res.push(f._compilerBreakLabel);
|
||||
return res;
|
||||
}
|
||||
|
||||
|
@ -2005,6 +2048,7 @@ module TDev.AST
|
|||
this.wr("function " + this.actionName + "(s ");
|
||||
a.getInParameters().forEach((l) => { this.wr(", " + this.localVarName(l.local)); });
|
||||
this.wr(") {\n");
|
||||
a._compilerBreakLabel = this.allocateLabel();
|
||||
|
||||
if (this.throwSyntaxError(a)) {
|
||||
this.wr("\n }\n");
|
||||
|
@ -2025,6 +2069,7 @@ module TDev.AST
|
|||
});
|
||||
|
||||
var jsNodes: JsStmt[] = this.dispatch(a.body);
|
||||
jsNodes.push(a._compilerBreakLabel)
|
||||
var prevMax = this.maxArgsToCheck + 1;
|
||||
this.insertFinalLabels(jsNodes);
|
||||
jsNodes.forEach((n) => n.forEachExpr((e:JsExpr) => {
|
||||
|
@ -2086,6 +2131,7 @@ module TDev.AST
|
|||
a.getInParameters().forEach((l) => { this.wr(", " + this.localVarName(l.local)); });
|
||||
var lab0 = this.allocateLabel();
|
||||
this.wr(") {\n")
|
||||
a._compilerBreakLabel = this.allocateLabel();
|
||||
|
||||
if (!this.throwSyntaxError(a)) {
|
||||
this.wr(
|
||||
|
@ -2144,6 +2190,7 @@ module TDev.AST
|
|||
|
||||
jsNodes.unshift(lab0);
|
||||
lab0.refs.push(lab0);
|
||||
jsNodes.push(a._compilerBreakLabel);
|
||||
var prevMax = this.maxArgsToCheck + 1;
|
||||
this.insertFinalLabels(jsNodes);
|
||||
jsNodes.forEach((n) => n.forEachExpr((e:JsExpr) => {
|
||||
|
|
|
@ -73,6 +73,18 @@ module TDev.AST {
|
|||
public visitForeach(stmt: Foreach) { return this.visitLoop(stmt); }
|
||||
public visitWhile(stmt: While) { return this.visitLoop(stmt); }
|
||||
|
||||
public visitBreak(stmt: Break) {
|
||||
return this.nextInBlock(stmt); // TODO wrong
|
||||
}
|
||||
|
||||
public visitReturn(stmt: Return) {
|
||||
return this.nextInBlock(stmt); // TODO wrong
|
||||
}
|
||||
|
||||
public visitShow(stmt: Show) {
|
||||
return this.nextInBlock(stmt);
|
||||
}
|
||||
|
||||
public visitExprStmt(stmt: ExprStmt) {
|
||||
return this.nextInBlock(stmt);
|
||||
}
|
||||
|
@ -987,6 +999,15 @@ module TDev.AST {
|
|||
visitExprStmt(n: ExprStmt) {
|
||||
this.visitExprHolderHolder(n);
|
||||
}
|
||||
visitBreak(n: Break) {
|
||||
this.visitExprHolderHolder(n);
|
||||
}
|
||||
visitReturn(n: Return) {
|
||||
this.visitExprHolderHolder(n);
|
||||
}
|
||||
visitShow(n: Show) {
|
||||
this.visitExprHolderHolder(n);
|
||||
}
|
||||
|
||||
// Non-recursive version of a topological sort to order our first
|
||||
// visit to the Action's nodes. Recursive versions are simpler
|
||||
|
@ -2253,6 +2274,14 @@ module TDev.AST {
|
|||
this.nowVisiting.canInline = false;
|
||||
this.visitChildren(n);
|
||||
}
|
||||
visitBreak(n: Break) {
|
||||
this.nowVisiting.canInline = false;
|
||||
this.visitChildren(n);
|
||||
}
|
||||
visitReturn(n: Return) {
|
||||
this.nowVisiting.canInline = false;
|
||||
this.visitChildren(n);
|
||||
}
|
||||
|
||||
// Build a new edge of the callgraph if calling another action
|
||||
visitCall(n: Call) {
|
||||
|
|
35
ast/json.ts
35
ast/json.ts
|
@ -613,6 +613,22 @@ module TDev.AST.Json
|
|||
}
|
||||
}
|
||||
|
||||
public visitShow(n:Show) {
|
||||
return {
|
||||
expr: n.expr,
|
||||
}
|
||||
}
|
||||
|
||||
public visitReturn(n:Return) {
|
||||
return {
|
||||
expr: n.expr,
|
||||
}
|
||||
}
|
||||
|
||||
public visitBreak(n:Break) {
|
||||
return { }
|
||||
}
|
||||
|
||||
public visitBox(n:Box) {
|
||||
return { body: n.body }
|
||||
}
|
||||
|
@ -1431,6 +1447,25 @@ module TDev.AST.Json
|
|||
block(n.body);
|
||||
},
|
||||
|
||||
"break": (n:JBreak) => {
|
||||
stmt(n)
|
||||
tw.keyword("break").op0(";").nl();
|
||||
},
|
||||
|
||||
"return": (n:JReturn) => {
|
||||
stmt(n)
|
||||
tw.keyword("return");
|
||||
selfEh(n, n.expr);
|
||||
tw.op0(";").nl();
|
||||
},
|
||||
|
||||
"show": (n:JShow) => {
|
||||
stmt(n)
|
||||
tw.keyword("do").id("show");
|
||||
selfEh(n, n.expr);
|
||||
tw.op0(";").nl();
|
||||
},
|
||||
|
||||
"if": (n:JIf) => {
|
||||
stmt(n)
|
||||
tw.keyword("if");
|
||||
|
|
|
@ -191,6 +191,10 @@ module TDev.AST.Json
|
|||
body:JStmt[];
|
||||
}
|
||||
|
||||
export interface JBreak extends JStmt {}
|
||||
export interface JReturn extends JStmt { expr: JExprHolder; }
|
||||
export interface JShow extends JStmt { expr: JExprHolder; }
|
||||
|
||||
// Sequences of if / else if / else statements are not represented the usual
|
||||
// way. That is, instead of having a structured AST:
|
||||
//
|
||||
|
|
|
@ -645,6 +645,14 @@ module TDev.AST {
|
|||
result = new While();
|
||||
(<While>result).body = <CodeBlock>getNewChild(0); // TODO - check cast?
|
||||
(<While>result).condition = mergeExprHolder(x => (<While>x).condition);
|
||||
} else if(test(Return)) {
|
||||
result = new Return();
|
||||
(<Return>result).expr = mergeExprHolder(x => (<Return>x).expr);
|
||||
} else if(test(Show)) {
|
||||
result = new Show();
|
||||
(<Show>result).expr = mergeExprHolder(x => (<Show>x).expr);
|
||||
} else if(test(Break)) {
|
||||
result = new Break();
|
||||
} else if(test(OptionalParameter)) {
|
||||
result = new OptionalParameter();
|
||||
(<OptionalParameter>result)._opt_name = getChange(x => (<OptionalParameter>x).getName());
|
||||
|
|
|
@ -978,8 +978,10 @@ module TDev { export module AST {
|
|||
var node;
|
||||
if (id == "box")
|
||||
node = Box;
|
||||
else if (id == "show")
|
||||
node = Show;
|
||||
else {
|
||||
this.error("expecting 'box' here");
|
||||
this.error("expecting 'box' or 'show' here");
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
|
@ -612,6 +612,23 @@ module TDev
|
|||
this.endKeyword("while"));
|
||||
}
|
||||
|
||||
public visitBreak(n:AST.Break)
|
||||
{
|
||||
return this.stmt(n, this.tline(this.kw("break")) + this.possibleError(n))
|
||||
}
|
||||
|
||||
public visitReturn(n:AST.Return)
|
||||
{
|
||||
return this.stmt(n, this.tline(this.kw("return") + this.expr(n.expr))
|
||||
+ this.possibleError(n))
|
||||
}
|
||||
|
||||
public visitShow(n:AST.Show)
|
||||
{
|
||||
return this.stmt(n, this.tline(this.kw("show") + this.expr(n.expr))
|
||||
+ this.possibleError(n))
|
||||
}
|
||||
|
||||
public visitBox(n:AST.Box)
|
||||
{
|
||||
return this.stmt(n,
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
// TODO events and async
|
||||
|
||||
// Next available error: TD200:
|
||||
// Next available error: TD205:
|
||||
|
||||
module TDev.AST
|
||||
{
|
||||
|
@ -200,18 +200,21 @@ module TDev.AST
|
|||
|
||||
public topApp:App;
|
||||
private currentAction:Action;
|
||||
private currentAnyAction:Stmt;
|
||||
private seenAwait = false;
|
||||
private numFixes = 0;
|
||||
private nothingLocals:LocalDef[] = [];
|
||||
private localScopes: LocalDef[][] = [[]];
|
||||
private readOnlyLocals:LocalDef[] = [];
|
||||
private writtenLocals:LocalDef[] = [];
|
||||
private currLoop:Stmt;
|
||||
|
||||
private inAtomic = false;
|
||||
private actionSection = ActionSection.Normal;
|
||||
private pageInit:Block;
|
||||
private pageDisplay:Block;
|
||||
private saveFixes = 0;
|
||||
private outLocals:LocalDef[] = [];
|
||||
|
||||
private allLocals :LocalDef[] = [];
|
||||
private recentErrors: string[] = [];
|
||||
|
@ -295,6 +298,7 @@ module TDev.AST
|
|||
case "while": return lf("TD129: 'while' condition wants {1:a}", whoExpects, tp);
|
||||
case "for": return lf("TD130: bound of 'for' wants {1:a}", whoExpects, tp);
|
||||
case "optional": return lf("TD186: this optional parameter wants {1:a}", whoExpects, tp);
|
||||
case "return": return lf("TD204: 'return' value wants {1:a}", whoExpects, tp);
|
||||
default: Util.die()
|
||||
}
|
||||
}
|
||||
|
@ -562,10 +566,12 @@ module TDev.AST
|
|||
private conditionalScope(f: () => any)
|
||||
{
|
||||
var prevWritten = this.writtenLocals.slice(0);
|
||||
var prevLoop = this.currLoop
|
||||
try {
|
||||
return this.scope(f);
|
||||
} finally {
|
||||
this.writtenLocals = prevWritten;
|
||||
this.currLoop = prevLoop
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -642,10 +648,52 @@ module TDev.AST
|
|||
this.updateStmtUsage(node);
|
||||
this.expect(node.condition, this.core.Boolean, 'while');
|
||||
this.conditionalScope(() => {
|
||||
this.currLoop = node;
|
||||
this.typeCheck(node.body);
|
||||
});
|
||||
}
|
||||
|
||||
public visitBreak(node:Break)
|
||||
{
|
||||
this.updateStmtUsage(node);
|
||||
node.loop = this.currLoop
|
||||
if (!node.loop)
|
||||
this.setNodeError(node, lf("TD200: 'break' can be only used inside a loop"))
|
||||
}
|
||||
|
||||
public visitShow(node:Show)
|
||||
{
|
||||
this.updateStmtUsage(node);
|
||||
this.expect(node.expr, null, "show")
|
||||
var tp = node.expr.getKind()
|
||||
if (tp == api.core.Unknown) return
|
||||
var show = tp.getProperty("post to wall")
|
||||
node.postCall = null;
|
||||
if (!show)
|
||||
this.setNodeError(node, lf("TD201: we don't know how to display {0}", tp.toString()))
|
||||
else
|
||||
node.postCall = mkFakeCall(PropertyRef.mkProp(show), [node.expr.parsed])
|
||||
}
|
||||
|
||||
public visitReturn(node:Return)
|
||||
{
|
||||
this.updateStmtUsage(node);
|
||||
node.retLocal = null;
|
||||
if (!node.expr.isPlaceholder()) {
|
||||
if (this.outLocals.length == 0)
|
||||
this.setNodeError(node, lf("TD202: the function doesn't have output parameters; return with value is not allowed"))
|
||||
else if (this.outLocals.length > 1)
|
||||
this.setNodeError(node, lf("TD203: the function has more than one output parameter; return with value is not allowed"))
|
||||
else {
|
||||
node.retLocal = this.outLocals[0]
|
||||
this.expect(node.expr, node.retLocal.getKind(), "return")
|
||||
this.recordLocalWrite(node.retLocal)
|
||||
}
|
||||
}
|
||||
node.action = this.currentAnyAction;
|
||||
this.checkAssignment(node)
|
||||
}
|
||||
|
||||
public visitActionParameter(node:ActionParameter)
|
||||
{
|
||||
}
|
||||
|
@ -711,6 +759,7 @@ module TDev.AST
|
|||
node.boundLocal._kind = this.core.Number;
|
||||
this.readOnlyLocals.push(node.boundLocal);
|
||||
this.conditionalScope(() => {
|
||||
this.currLoop = node;
|
||||
this.declareLocal(node.boundLocal);
|
||||
this.typeCheck(node.body);
|
||||
});
|
||||
|
@ -738,6 +787,7 @@ module TDev.AST
|
|||
node.boundLocal._kind = ek;
|
||||
this.readOnlyLocals.push(node.boundLocal);
|
||||
this.conditionalScope(() => {
|
||||
this.currLoop = node;
|
||||
this.declareLocal(node.boundLocal);
|
||||
this.typeCheck(node.conditions);
|
||||
this.typeCheck(node.body);
|
||||
|
@ -761,6 +811,7 @@ module TDev.AST
|
|||
this.readOnlyLocals = [];
|
||||
this.allLocals = [];
|
||||
this.currentAction = node;
|
||||
this.currentAnyAction = node;
|
||||
node.clearError();
|
||||
this.actionSection = ActionSection.Normal;
|
||||
this.inAtomic = node.isAtomic;
|
||||
|
@ -768,6 +819,7 @@ module TDev.AST
|
|||
this.scope(() => {
|
||||
// TODO in - read-only?
|
||||
var prevErr = this.errorCount;
|
||||
this.outLocals = node.getOutParameters().map((p) => p.local)
|
||||
|
||||
this.typeResolver.visitAction(node);
|
||||
|
||||
|
@ -791,7 +843,7 @@ module TDev.AST
|
|||
this.setNodeError(node, lf("TD171: currently action types support at most one output parameter; sorry"))
|
||||
}
|
||||
} else
|
||||
this.checkAssignment(node, node.getOutParameters().map((p) => p.local));
|
||||
this.checkAssignment(node);
|
||||
node._hasErrors = this.errorCount > prevErr;
|
||||
node.allLocals = this.allLocals;
|
||||
});
|
||||
|
@ -1049,9 +1101,9 @@ module TDev.AST
|
|||
this.updateStmtUsage(expr, "var");
|
||||
}
|
||||
|
||||
private checkAssignment(node:Stmt, vars:LocalDef[])
|
||||
private checkAssignment(node:Stmt)
|
||||
{
|
||||
var unassigned = vars.filter((v) => this.writtenLocals.indexOf(v) < 0);
|
||||
var unassigned = this.outLocals.filter((v) => this.writtenLocals.indexOf(v) < 0);
|
||||
if (unassigned.length > 0) {
|
||||
node.addHint(
|
||||
lf("parameter{0:s} {1} may be unassigned before the action finishes",
|
||||
|
@ -1067,6 +1119,8 @@ module TDev.AST
|
|||
var prevWritten = this.writtenLocals;
|
||||
var prevSect = this.actionSection;
|
||||
var prevAtomic = this.inAtomic;
|
||||
var prevOut = this.outLocals;
|
||||
var prevAct = this.currentAnyAction;
|
||||
|
||||
this.writtenLocals = [];
|
||||
|
||||
|
@ -1081,6 +1135,8 @@ module TDev.AST
|
|||
this.readOnlyLocals = prevReadOnly;
|
||||
this.inAtomic = prevAtomic;
|
||||
this.actionSection = prevSect;
|
||||
this.outLocals = prevOut;
|
||||
this.currentAnyAction = prevAct;
|
||||
}
|
||||
})
|
||||
}
|
||||
|
@ -1089,10 +1145,12 @@ module TDev.AST
|
|||
private typeCheckInlineAction(inl:InlineAction)
|
||||
{
|
||||
this.actionScope(inl.name.getKind(), () => {
|
||||
this.currentAnyAction = inl;
|
||||
inl.inParameters.forEach((d) => this.declareLocal(d));
|
||||
inl.outParameters.forEach((d) => this.declareLocal(d));
|
||||
this.outLocals = inl.outParameters.slice(0);
|
||||
this.typeCheck(inl.body);
|
||||
this.checkAssignment(inl, inl.outParameters);
|
||||
this.checkAssignment(inl);
|
||||
})
|
||||
}
|
||||
|
||||
|
@ -1399,6 +1457,12 @@ module TDev.AST
|
|||
t._kind = ak || this.core.Unknown
|
||||
}
|
||||
|
||||
private recordLocalWrite(loc:LocalDef)
|
||||
{
|
||||
if (this.writtenLocals.indexOf(loc) < 0)
|
||||
this.writtenLocals.push(loc);
|
||||
}
|
||||
|
||||
private handleAssignment(t:Call, args:Expr[])
|
||||
{
|
||||
t._kind = this.core.Nothing;
|
||||
|
@ -1466,8 +1530,7 @@ module TDev.AST
|
|||
else
|
||||
this.markError(trg, lf("TD108: you cannot assign to the local variable '{0}'", name));
|
||||
} else {
|
||||
if (this.writtenLocals.indexOf(loc) < 0)
|
||||
this.writtenLocals.push(loc);
|
||||
this.recordLocalWrite(loc)
|
||||
}
|
||||
}
|
||||
this.typeCheckExpr(trg);
|
||||
|
@ -1586,11 +1649,7 @@ module TDev.AST
|
|||
case "javascript":
|
||||
case "javascript async":
|
||||
if (!checkArgumentCount(3)) return;
|
||||
this.currentAction.getOutParameters().forEach(p => {
|
||||
var loc = p.local
|
||||
if (this.writtenLocals.indexOf(loc) < 0)
|
||||
this.writtenLocals.push(loc);
|
||||
})
|
||||
this.currentAction.getOutParameters().forEach(p => this.recordLocalWrite(p.local))
|
||||
this.lintJavaScript(t.args[2].getStringLiteral(), /async/.test(t.prop().getName()))
|
||||
break;
|
||||
case "import":
|
||||
|
|
|
@ -134,6 +134,9 @@ module TDev.Browser {
|
|||
comment: true,
|
||||
foreach: true,
|
||||
boxed: true,
|
||||
show: true,
|
||||
"return": true,
|
||||
"break": true,
|
||||
stringConcatProperty: true,
|
||||
// hub
|
||||
scriptAddToChannel: true,
|
||||
|
|
|
@ -74,6 +74,21 @@ module TDev
|
|||
node: "do box { }",
|
||||
widget: "boxed"
|
||||
},
|
||||
{
|
||||
name: "show", desc: lf("show value on the screen"), tick: Ticks.codeShow,
|
||||
node: "do show \\u0001need_String\\u003Awhat_to_show ;",
|
||||
widget: "show"
|
||||
},
|
||||
{
|
||||
name: "break", desc: lf("stop a loop"), tick: Ticks.codeBreak,
|
||||
node: "break;",
|
||||
widget: "break"
|
||||
},
|
||||
{
|
||||
name: "return", desc: lf("stop a function"), tick: Ticks.codeReturn,
|
||||
node: "return ... ;",
|
||||
widget: "return"
|
||||
},
|
||||
].filter(btn => !btn.widget || TheEditor.widgetEnabled(btn.widget));
|
||||
}
|
||||
|
||||
|
|
|
@ -135,6 +135,9 @@ module TDev {
|
|||
|
||||
codeAddAbove,
|
||||
codeAddBelow,
|
||||
codeShow,
|
||||
codeReturn,
|
||||
codeBreak,
|
||||
codeBoxed,
|
||||
codeCopy,
|
||||
codeCopySelection,
|
||||
|
|
Загрузка…
Ссылка в новой задаче