- Incomplete, partial translation for function definitions and function calls.

(A few troubles related to type inference.)
This commit is contained in:
Jonathan Protzenko 2015-04-07 12:00:03 -07:00
Родитель 3d1a2c86f7
Коммит 3df04bec36
2 изменённых файлов: 71 добавлений и 17 удалений

11
www/blockly/blockly.d.ts поставляемый
Просмотреть файл

@ -2,8 +2,7 @@ declare module Blockly {
class Block {
static obtain(workspace: Workspace, prototypeName?: string): Block;
// If type is equals to "foo_bar" and [FooBarBlock] exists, then you
// may cast to it.
// May allow downcasting (see below).
type: string;
id: string;
@ -17,11 +16,17 @@ declare module Blockly {
getNextBlock(): Block;
}
class ControlsIfBlock extends Block {
// if type == controls_if
class IfBlock extends Block {
elseifCount_: number;
elseCount_: number;
}
// if type is one of "procedures_def{,no}return", or "procedures_call{,no}return"
class DefOrCallBlock extends Block {
arguments_: string[];
}
class Workspace {
clear(): void;
dispose(): void;

Просмотреть файл

@ -77,18 +77,22 @@ module Helpers {
};
}
// Assumes its parameter [p] is in the [knownPropertyRefs] table.
export function mkSimpleCall(p: string, args: J.JExpr[]): J.JExpr {
assert(knownPropertyRefs[p] != undefined);
export function mkCall(name: string, parent: string, args: J.JExpr[]): J.JExpr {
return {
nodeType: "call",
id: null,
name: p,
parent: knownPropertyRefs[p],
name: name,
parent: parent,
args: args,
};
}
// Assumes its parameter [p] is in the [knownPropertyRefs] table.
export function mkSimpleCall(p: string, args: J.JExpr[]): J.JExpr {
assert(knownPropertyRefs[p] != undefined);
return mkCall(p, knownPropertyRefs[p], args);
}
export function mkTypeRef(t: string): J.JTypeRef {
// The interface is a lie -- actually, this type is just string.
return <any> t;
@ -189,14 +193,19 @@ module Helpers {
return mkExprStmt(expr);
}
export function mkAction(name: string, body: J.JStmt[]): J.JAction {
export function mkAction(
name: string,
body: J.JStmt[],
inParams: J.JLocalDef[] = [],
outParams: J.JLocalDef[] = []): J.JAction
{
return {
nodeType: "action",
id: null,
name: name,
body: body,
inParameters: [],
outParameters: [],
inParameters: inParams,
outParameters: outParams,
isPrivate: false,
isOffline: false,
isQuery: false,
@ -233,6 +242,9 @@ module Helpers {
import H = Helpers;
// Infers the expected type of an expression by looking at the untranslated
// block and figuring out, from the look of it, what type of expression it
// holds.
function inferType(e: Environment, b: B.Block): J.JTypeRef {
switch (b.type) {
case "math_number":
@ -305,6 +317,14 @@ function compileNot(e: Environment, b: B.Block): J.JExpr {
return H.mkSimpleCall("not", [expr]);
}
function compileCall(e: Environment, b: B.DefOrCallBlock): J.JExpr {
var f = b.getFieldValue("NAME");
var args = b.arguments_.map((x: any, i: number) => {
return compileExpression(e, b.getInputTargetBlock("ARG"+i));
});
return H.mkCall(f, "code", args);
}
function compileExpression(e: Environment, b: B.Block): J.JExpr {
switch (b.type) {
case "math_number":
@ -321,6 +341,8 @@ function compileExpression(e: Environment, b: B.Block): J.JExpr {
return compileVariableGet(e, b);
case "text":
return compileText(e, b);
case "procedures_callreturn":
return compileCall(e, <B.DefOrCallBlock> b);
}
throw (b.type + " is not an expression block or is not supported");
// unreachable
@ -364,7 +386,7 @@ var empty: Environment = {
// Statements
///////////////////////////////////////////////////////////////////////////////
function compileControlsIf(e: Environment, b: B.ControlsIfBlock): J.JStmt[] {
function compileControlsIf(e: Environment, b: B.IfBlock): J.JStmt[] {
var stmts: J.JIf[] = [];
for (var i = 0; i <= b.elseifCount_; ++i) {
var cond = compileExpression(e, b.getInputTargetBlock("IF"+i));
@ -442,7 +464,7 @@ function compileStatements(e: Environment, b: B.Block): J.JStmt[] {
while (b) {
switch (b.type) {
case 'controls_if':
append(stmts, compileControlsIf(e, <B.ControlsIfBlock> b));
append(stmts, compileControlsIf(e, <B.IfBlock> b));
break;
case 'controls_for':
@ -468,6 +490,22 @@ function compileStatements(e: Environment, b: B.Block): J.JStmt[] {
return stmts;
}
function compileFunction(e: Environment, b: B.DefOrCallBlock): J.JAction {
assert(isFunctionDefinition(b));
var fName = b.getFieldValue("NAME");
var inParams: J.JLocalDef[] = [];
var outParams: J.JLocalDef[] = [];
e = b.arguments_.reduce((e: Environment, name: string) => {
var t = H.mkTypeRef("Unknown");
inParams.push(H.mkDef(name, t));
return extend(e, { name: name, type: t });
}, e);
var body = compileStatements(e, b.getInputTargetBlock("STACK"));
return H.mkAction(fName, body, inParams, outParams);
}
///////////////////////////////////////////////////////////////////////////////
// Top-level definitions for compiling an entire blockly workspace
@ -477,11 +515,22 @@ interface CompileOptions {
description: string;
}
function isFunctionDefinition(b: B.Block) {
return (b.type == "procedures_defreturn" ||
b.type == "procedures_defnoreturn");
}
function compileWorkspace(b: B.Workspace, options: CompileOptions): J.JApp {
var actions = b.getTopBlocks(true).map((b: B.Block, i: number) => {
var body = compileStatements(empty, b);
var name = "main"+(i == 0 ? "" : i);
return H.mkAction(name, body);
var i = 0;
var actions = b.getTopBlocks(true).map((b: B.Block) => {
if (isFunctionDefinition(b)) {
return compileFunction(empty, <B.DefOrCallBlock> b);
} else {
var body = compileStatements(empty, b);
var name = "main"+(i == 0 ? "" : i);
i++;
return H.mkAction(name, body);
}
});
return H.mkApp(options.name, options.description, actions);
}