Hook-up app->thumb
This commit is contained in:
Родитель
991de5a045
Коммит
7a073cd014
|
@ -1816,6 +1816,7 @@ module TDev.AST {
|
||||||
public _isActionTypeDef:boolean;
|
public _isActionTypeDef:boolean;
|
||||||
public _compilerInlineAction:InlineAction;
|
public _compilerInlineAction:InlineAction;
|
||||||
public _compilerParentAction:Action; // this is only set for synthetic actions created in compiler for lambda expressions
|
public _compilerParentAction:Action; // this is only set for synthetic actions created in compiler for lambda expressions
|
||||||
|
public _compilerInlineBody:Stmt;
|
||||||
public _skipIntelliProfile:boolean;
|
public _skipIntelliProfile:boolean;
|
||||||
public allLocals:LocalDef[];
|
public allLocals:LocalDef[];
|
||||||
public accept(v:NodeVisitor) { return v.visitAction(this); }
|
public accept(v:NodeVisitor) { return v.visitAction(this); }
|
||||||
|
@ -1855,6 +1856,13 @@ module TDev.AST {
|
||||||
return res
|
return res
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public getShimName():string
|
||||||
|
{
|
||||||
|
var shm = /{shim:([^{}]*)}/.exec(this.getDescription())
|
||||||
|
if (shm) return shm[1]
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
|
||||||
public getFlags()
|
public getFlags()
|
||||||
{
|
{
|
||||||
var flags = !this.isAtomic ? PropertyFlags.Async : PropertyFlags.None
|
var flags = !this.isAtomic ? PropertyFlags.Async : PropertyFlags.None
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
|
|
||||||
// TODO events and async
|
// TODO events and async
|
||||||
|
|
||||||
// Next available error: TD212:
|
// Next available error: TD214:
|
||||||
|
|
||||||
module TDev.AST
|
module TDev.AST
|
||||||
{
|
{
|
||||||
|
@ -96,7 +96,7 @@ module TDev.AST
|
||||||
private isTopExpr = false;
|
private isTopExpr = false;
|
||||||
|
|
||||||
static lastStoreLocalsAt:ExprHolder;
|
static lastStoreLocalsAt:ExprHolder;
|
||||||
static lintThumb : (asm:string, err:(msg:string) => void) => void;
|
static lintThumb : (a:Action, asm:string, err:(msg:string) => void) => void;
|
||||||
|
|
||||||
constructor() {
|
constructor() {
|
||||||
super()
|
super()
|
||||||
|
@ -864,7 +864,7 @@ module TDev.AST
|
||||||
node.clearError();
|
node.clearError();
|
||||||
this.actionSection = ActionSection.Normal;
|
this.actionSection = ActionSection.Normal;
|
||||||
this.inAtomic = node.isAtomic;
|
this.inAtomic = node.isAtomic;
|
||||||
this.inShim = this.topApp.entireShim || /{shim:.*}/.test(node.getDescription())
|
this.inShim = this.topApp.entireShim || node.getShimName() != null;
|
||||||
|
|
||||||
this.scope(() => {
|
this.scope(() => {
|
||||||
// TODO in - read-only?
|
// TODO in - read-only?
|
||||||
|
@ -1778,8 +1778,11 @@ module TDev.AST
|
||||||
break;
|
break;
|
||||||
case "thumb":
|
case "thumb":
|
||||||
if (!checkArgumentCount(2)) return;
|
if (!checkArgumentCount(2)) return;
|
||||||
|
if (!this.inShim)
|
||||||
|
this.markError(t, lf("TD213: app->thumb only supported inside of {shim:}"))
|
||||||
|
this.currentAction.getOutParameters().forEach(p => this.recordLocalWrite(p.local))
|
||||||
if (TypeChecker.lintThumb)
|
if (TypeChecker.lintThumb)
|
||||||
TypeChecker.lintThumb(t.args[1].getStringLiteral(), e => this.markError(t, e))
|
TypeChecker.lintThumb(this.currentAction, t.args[1].getStringLiteral(), e => this.markError(t, e))
|
||||||
break;
|
break;
|
||||||
case "import":
|
case "import":
|
||||||
if (!checkArgumentCount(4)) return;
|
if (!checkArgumentCount(4)) return;
|
||||||
|
|
|
@ -745,8 +745,16 @@ module TDev.AST.Bytecode
|
||||||
{
|
{
|
||||||
useAction(a:Action)
|
useAction(a:Action)
|
||||||
{
|
{
|
||||||
if (/{shim:.*}/.test(a.getDescription()))
|
if (a.getShimName() != null && !a._compilerInlineBody) {
|
||||||
return
|
a.body.stmts.forEach(s => {
|
||||||
|
var str = AST.getEmbeddedLangaugeToken(s)
|
||||||
|
if (str && (<ExprStmt>s).expr.parsed.getCalledProperty().getName() == "thumb") {
|
||||||
|
a._compilerInlineBody = s;
|
||||||
|
}
|
||||||
|
})
|
||||||
|
if (!a._compilerInlineBody)
|
||||||
|
return
|
||||||
|
}
|
||||||
super.useAction(a)
|
super.useAction(a)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -948,6 +956,11 @@ module TDev.AST.Bytecode
|
||||||
this.proc.emit("push {r1}");
|
this.proc.emit("push {r1}");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
reportError(msg:string)
|
||||||
|
{
|
||||||
|
Util.userError(msg)
|
||||||
|
}
|
||||||
|
|
||||||
handleActionCall(e:Call)
|
handleActionCall(e:Call)
|
||||||
{
|
{
|
||||||
var aa = e.calledExtensionAction() || e.calledAction()
|
var aa = e.calledExtensionAction() || e.calledAction()
|
||||||
|
@ -962,15 +975,15 @@ module TDev.AST.Bytecode
|
||||||
Util.assert(args.length == aa.getInParameters().length)
|
Util.assert(args.length == aa.getInParameters().length)
|
||||||
|
|
||||||
var a:Action = aa._compilerInfo || aa
|
var a:Action = aa._compilerInfo || aa
|
||||||
var shm = /{shim:([^{}]*)}/.exec(a.getDescription())
|
var shm = a.getShimName();
|
||||||
var hasret = !!aa.getOutParameters()[0]
|
var hasret = !!aa.getOutParameters()[0]
|
||||||
|
|
||||||
if (shm && shm[1] == "TD_NOOP") {
|
if (shm == "TD_NOOP") {
|
||||||
Util.assert(!hasret)
|
Util.assert(!hasret)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if (shm && /^micro_bit::(createImage|showAnimation|showLeds)$/.test(shm[1])) {
|
if (/^micro_bit::(createImage|showAnimation|showLeds)$/.test(shm)) {
|
||||||
Util.assert(args[0].getLiteral() != null)
|
Util.assert(args[0].getLiteral() != null)
|
||||||
this.emitImageLiteral(args[0].getLiteral())
|
this.emitImageLiteral(args[0].getLiteral())
|
||||||
args.shift()
|
args.shift()
|
||||||
|
@ -982,25 +995,41 @@ module TDev.AST.Bytecode
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
if (shm) {
|
if (shm != null) {
|
||||||
var mask = this.getMask(args)
|
var mask = this.getMask(args)
|
||||||
var msg = "{shim:" + shm[1] + "} from " + a.getName()
|
var msg = "{shim:" + shm + "} from " + a.getName()
|
||||||
if (!shm[1])
|
if (!shm)
|
||||||
Util.oops("called " + msg)
|
Util.oops("called " + msg + " (with empty {shim:}")
|
||||||
|
|
||||||
var inf = lookupFunc(shm[1])
|
var inf = lookupFunc(shm)
|
||||||
|
|
||||||
if (!inf)
|
if (a._compilerInlineBody) {
|
||||||
Util.oops("no such " + msg)
|
if (inf)
|
||||||
|
this.reportError(lf("app->thumb inline body not allowed in {shim:{0}} (already defined in runtime)", shm))
|
||||||
if (!hasret) {
|
funcInfo[shm] = {
|
||||||
Util.assert(inf.type == "P", "expecting procedure for " + msg);
|
type: hasret ? "F" : "P",
|
||||||
|
args: a.getInParameters().length,
|
||||||
|
idx: 0,
|
||||||
|
value: 0
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
this.proc.emitCall(shm, mask)
|
||||||
|
} finally {
|
||||||
|
delete funcInfo[shm]
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
Util.assert(inf.type == "F", "expecting function for " + msg);
|
if (!inf)
|
||||||
}
|
Util.oops("no such " + msg)
|
||||||
Util.assert(args.length == inf.args, "argument number mismatch: " + args.length + " vs " + inf.args + " in " + msg)
|
|
||||||
|
|
||||||
this.proc.emitCall(shm[1], mask)
|
if (!hasret) {
|
||||||
|
Util.assert(inf.type == "P", "expecting procedure for " + msg);
|
||||||
|
} else {
|
||||||
|
Util.assert(inf.type == "F", "expecting function for " + msg);
|
||||||
|
}
|
||||||
|
Util.assert(args.length == inf.args, "argument number mismatch: " + args.length + " vs " + inf.args + " in " + msg)
|
||||||
|
|
||||||
|
this.proc.emitCall(shm, mask)
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
this.proc.emit("bl " + this.procIndex(a).label)
|
this.proc.emit("bl " + this.procIndex(a).label)
|
||||||
if (args.length > 0) {
|
if (args.length > 0) {
|
||||||
|
@ -1395,6 +1424,15 @@ module TDev.AST.Bytecode
|
||||||
|
|
||||||
this.proc = this.procIndex(a);
|
this.proc = this.procIndex(a);
|
||||||
|
|
||||||
|
if (a.getShimName() != null) {
|
||||||
|
var body = AST.getEmbeddedLangaugeToken(a._compilerInlineBody)
|
||||||
|
Util.assert(body != null)
|
||||||
|
Util.assert(body.getStringLiteral() != null)
|
||||||
|
this.proc.emit(body.getStringLiteral())
|
||||||
|
this.proc.emit("@stackempty func");
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
var ret = this.proc.mkLabel("actret")
|
var ret = this.proc.mkLabel("actret")
|
||||||
a._compilerBreakLabel = ret;
|
a._compilerBreakLabel = ret;
|
||||||
this.dispatch(a.body)
|
this.dispatch(a.body)
|
||||||
|
@ -1461,6 +1499,25 @@ module TDev.AST.Bytecode
|
||||||
p.action = a;
|
p.action = a;
|
||||||
this.binary.addProc(p)
|
this.binary.addProc(p)
|
||||||
|
|
||||||
|
var shimname = a.getShimName()
|
||||||
|
if (shimname != null) {
|
||||||
|
Util.assert(!!a._compilerInlineBody)
|
||||||
|
|
||||||
|
if (!/^\w+$/.test(shimname))
|
||||||
|
this.reportError(lf("invalid inline shim name: {shim:{0}}", shimname))
|
||||||
|
|
||||||
|
if (a.getInParameters().length > 4)
|
||||||
|
this.reportError(lf("inline shims support only up to 4 arguments"));
|
||||||
|
|
||||||
|
this.proc.label = shimname
|
||||||
|
|
||||||
|
this.proc.emit(".section code");
|
||||||
|
this.proc.emitLbl(this.proc.label);
|
||||||
|
this.proc.emit("@stackmark func");
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
var inparms = a.getInParameters().map(p => p.local)
|
var inparms = a.getInParameters().map(p => p.local)
|
||||||
this.proc.args = inparms.map((p, i) => {
|
this.proc.args = inparms.map((p, i) => {
|
||||||
var l = new Location(i, p);
|
var l = new Location(i, p);
|
||||||
|
@ -1477,6 +1534,7 @@ module TDev.AST.Bytecode
|
||||||
this.proc.pushLocals();
|
this.proc.pushLocals();
|
||||||
|
|
||||||
visitStmts(a.body, s => {
|
visitStmts(a.body, s => {
|
||||||
|
|
||||||
if (s instanceof ExprStmt) {
|
if (s instanceof ExprStmt) {
|
||||||
var ai = (<ExprStmt>s).expr.assignmentInfo()
|
var ai = (<ExprStmt>s).expr.assignmentInfo()
|
||||||
if (ai) {
|
if (ai) {
|
||||||
|
@ -1547,13 +1605,13 @@ module TDev.AST.Bytecode
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function lintThumb(asm:string, err:(msg:string) => void)
|
function lintThumb(act:Action, asm:string, err:(msg:string) => void)
|
||||||
{
|
{
|
||||||
setup();
|
setup();
|
||||||
var code =
|
var code =
|
||||||
".section code\n" +
|
".section code\n" +
|
||||||
"@stackmark base\n" +
|
"@stackmark base\n" +
|
||||||
"_start:\n" +
|
act.getShimName() + ":\n" +
|
||||||
asm + "\n" +
|
asm + "\n" +
|
||||||
"@stackempty base\n"
|
"@stackempty base\n"
|
||||||
var b = new Thumb.Binary();
|
var b = new Thumb.Binary();
|
||||||
|
@ -1563,14 +1621,15 @@ module TDev.AST.Bytecode
|
||||||
|
|
||||||
if (b.errors.length > 0) {
|
if (b.errors.length > 0) {
|
||||||
b.errors.forEach(e => console.log(e.message))
|
b.errors.forEach(e => console.log(e.message))
|
||||||
err(b.errors.map(e => e.message).join("\n"))
|
err(lf("TD212: thumb assembler error") + "\n" +
|
||||||
|
b.errors.map(e => e.message).join("\n"))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
TypeChecker.lintThumb = lintThumb;
|
TypeChecker.lintThumb = lintThumb;
|
||||||
|
|
||||||
function asmline(s:string)
|
function asmline(s:string)
|
||||||
{
|
{
|
||||||
if (!/:$/.test(s))
|
if (!/(^\s)|(:$)/.test(s))
|
||||||
s = " " + s
|
s = " " + s
|
||||||
return s + "\n"
|
return s + "\n"
|
||||||
}
|
}
|
||||||
|
|
Загрузка…
Ссылка в новой задаче