Merge branch 'master' of github.com:Microsoft/TouchDevelop
This commit is contained in:
Коммит
3d339de436
|
@ -35,6 +35,7 @@ module TDev {
|
|||
export var isWindows8plus = false;
|
||||
export var isCompiledApp = false;
|
||||
export var isWP8app = false;
|
||||
export var isHosted = false;
|
||||
export var browser = BrowserSoftware.unknown;
|
||||
export var browserVersion = 0;
|
||||
export var browserVersion2 = 0; // not set for pinned iOS apps; look at webkitVersion instead
|
||||
|
@ -113,6 +114,11 @@ module TDev {
|
|||
export function detect() {
|
||||
startTimestamp = new Date().getTime(); // no Util here
|
||||
|
||||
if ((<any>window).touchDevelopExec || (<any>window).mcefQuery) {
|
||||
isHosted = true;
|
||||
Browser.screenshots = true;
|
||||
}
|
||||
|
||||
if ((<any>window).isNodeJS) {
|
||||
isNodeJS = true
|
||||
isHeadless = true
|
||||
|
|
|
@ -191,9 +191,7 @@ module TDev
|
|||
public additionalFullScreenButtons(): HTMLElement[] {
|
||||
var btns = [];
|
||||
if (ScriptEditorWorldInfo.status == "published")
|
||||
btns.push(
|
||||
HTML.mkRoundButton("svg:camera,black", lf("screenshot"), Ticks.wallScreenshot, () => this.takeScreenshot())
|
||||
);
|
||||
btns.push(HTML.mkRoundButton("svg:camera,black", lf("screenshot"), Ticks.wallScreenshot, () => this.takeScreenshot()));
|
||||
return btns;
|
||||
}
|
||||
|
||||
|
|
|
@ -214,7 +214,11 @@ module TDev {
|
|||
case MessageType.Upgrade:
|
||||
var message2 = <Message_Upgrade> event.data;
|
||||
var text = AST.Json.serialize(message2.ast);
|
||||
console.log(text);
|
||||
Browser.TheHost.openNewScriptAsync({
|
||||
editorName: "touchdevelop",
|
||||
scriptName: message2.name,
|
||||
scriptText: text
|
||||
});
|
||||
break;
|
||||
|
||||
default:
|
||||
|
|
|
@ -213,7 +213,7 @@ module TDev.Browser {
|
|||
}
|
||||
|
||||
export function hubTheme(): HubTheme {
|
||||
var key = localStorage.getItem("hubTheme");
|
||||
var key = localStorage.getItem("hubTheme");
|
||||
return key ? Browser.hubThemes[key] : undefined;
|
||||
}
|
||||
|
||||
|
|
|
@ -64,6 +64,7 @@ module TDev {
|
|||
|
||||
export interface Message_Upgrade extends Message {
|
||||
type: MessageType; // == MessageType.Message_Upgrade
|
||||
name: string;
|
||||
ast: any // AST.Json.JApp
|
||||
}
|
||||
|
||||
|
|
Различия файлов скрыты, потому что одна или несколько строк слишком длинны
65
lib/App.ts
65
lib/App.ts
|
@ -300,7 +300,7 @@ module TDev.RT {
|
|||
//? Indicates if the `app->host_exec` action can be used to run host commands.
|
||||
//@ betaOnly
|
||||
public has_host(): boolean {
|
||||
return !!(<any>window).mcefQuery || !!(<any>window).touchDevelopExec;
|
||||
return Browser.isHosted;
|
||||
}
|
||||
|
||||
//? Where are we running from: "editor", "website", "nodejs", "mobileapp", "plugin"
|
||||
|
@ -713,39 +713,44 @@ module TDev.RT {
|
|||
return r
|
||||
}
|
||||
|
||||
export function hostExecAsync(message: string): Promise {
|
||||
return new Promise((onSuccess, onError, onProgress) => {
|
||||
var mcefQuery = (<any>window).mcefQuery;
|
||||
if (mcefQuery) {
|
||||
mcefQuery({
|
||||
request: message,
|
||||
persistent: false,
|
||||
onSuccess: function (response) {
|
||||
onSuccess(response);
|
||||
},
|
||||
onFailure: function (error_code, error_message) {
|
||||
onSuccess(JSON.stringify({ error: error_code, message: error_message }));
|
||||
}
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
var exec = (<any>window).touchDevelopExec;
|
||||
if (!exec) {
|
||||
App.log("window.touchDevelopExec function not defined");
|
||||
onSuccess(undefined);
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
exec(message,(result) => { onSuccess(result); });
|
||||
}
|
||||
catch (e) {
|
||||
App.logEvent(App.DEBUG, "app", "touchDevelopExec failed", undefined);
|
||||
onSuccess(undefined);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
//? Invokes the host to execute a command described in the message and returns the response. There is no restriction on the format of the request and response. If not available or errored, returns invalid.
|
||||
//@ async readsMutable returns(string) betaOnly
|
||||
export function host_exec(message: string, r: ResumeCtx) {
|
||||
var mcefQuery = (<any>window).mcefQuery;
|
||||
if (mcefQuery) {
|
||||
mcefQuery({
|
||||
request: message,
|
||||
persistent: false,
|
||||
onSuccess: function (response) {
|
||||
r.resumeVal(response);
|
||||
},
|
||||
onFailure: function (error_code, error_message) {
|
||||
r.resumeVal(JSON.stringify({ error: error_code, message: error_message }));
|
||||
}
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
var exec = (<any>window).touchDevelopExec;
|
||||
if (!exec) {
|
||||
App.log("window.touchDevelopExec function not defined");
|
||||
r.resumeVal(undefined);
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
exec(message, (result) => { r.resumeVal(result); });
|
||||
}
|
||||
catch (e) {
|
||||
App.logEvent(App.DEBUG, "app", "touchDevelopExec failed", undefined);
|
||||
r.resumeVal(undefined);
|
||||
}
|
||||
return hostExecAsync(message).done(resp => r.resumeVal(resp));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
13
lib/Wall.ts
13
lib/Wall.ts
|
@ -470,6 +470,19 @@ module TDev.RT {
|
|||
|
||||
export module ScreenshotManager {
|
||||
export var toScreenshotURLAsync = (rt: RuntimeHost): Promise => { // string {
|
||||
// TODO: move somewhere else
|
||||
if (App.env().has_host()) {
|
||||
var durl: string;
|
||||
return App.hostExecAsync("screen.min")
|
||||
.then(() => new Promise((onSuccess, onError, onProcess) => {
|
||||
Util.setTimeout(100,() => onSuccess(undefined));
|
||||
})).then(() => App.hostExecAsync("screen.screenshot"))
|
||||
.then((url) => {
|
||||
durl = url;
|
||||
return App.hostExecAsync("screen.show");
|
||||
}).then(() => durl);
|
||||
}
|
||||
|
||||
var c = rt.toScreenshotCanvas();
|
||||
try {
|
||||
var data = c ? c.toDataURL('image/png') : undefined;
|
||||
|
|
|
@ -328,6 +328,7 @@ module TDev {
|
|||
name: getName(),
|
||||
description: getDescription()
|
||||
}),
|
||||
name: getName()+" (converted)",
|
||||
});
|
||||
});
|
||||
$("#command-run").addEventListener("click", () => {
|
||||
|
|
|
@ -18,7 +18,7 @@ declare module Blockly {
|
|||
}
|
||||
|
||||
class ControlsIfBlock extends Block {
|
||||
elseIfCount_: number;
|
||||
elseifCount_: number;
|
||||
elseCount_: number;
|
||||
}
|
||||
|
||||
|
|
|
@ -10,25 +10,47 @@ import B = Blockly;
|
|||
|
||||
// A series of utility functions for constructing various J* AST nodes.
|
||||
module Helpers {
|
||||
function assert(x: boolean) {
|
||||
if (!x)
|
||||
throw "Assertion failure";
|
||||
}
|
||||
|
||||
// Digits are operators...
|
||||
export function mkDigit(x: string): J.JOperator {
|
||||
return mkOp(x);
|
||||
}
|
||||
|
||||
export function mkStringLiteral(x: string): J.JStringLiteral {
|
||||
return {
|
||||
nodeType: "stringLiteral",
|
||||
id: null,
|
||||
value: x
|
||||
};
|
||||
}
|
||||
|
||||
export function mkOp(x: string): J.JOperator {
|
||||
return {
|
||||
nodeType: "operator",
|
||||
id: "TODO",
|
||||
id: null,
|
||||
op: x
|
||||
};
|
||||
}
|
||||
|
||||
export function mkPropertyRef(x: string): J.JPropertyRef {
|
||||
return {
|
||||
nodeType: "propertyRef",
|
||||
id: null,
|
||||
name: x,
|
||||
parent: null,
|
||||
};
|
||||
}
|
||||
|
||||
// Generates a local definition for [x] at type [t]; this is not enough to
|
||||
// properly define a variable, though (see [mkDefAndAssign]).
|
||||
export function mkDef(x: string, t: string): J.JLocalDef {
|
||||
return {
|
||||
nodeType: "localDef",
|
||||
id: "TODO",
|
||||
id: null,
|
||||
name: x,
|
||||
type: <any> t, // the interface is a lie
|
||||
};
|
||||
|
@ -38,7 +60,7 @@ module Helpers {
|
|||
export function mkLocalRef(x: string): J.JLocalRef {
|
||||
return {
|
||||
nodeType: "localRef",
|
||||
id: "TODO",
|
||||
id: null,
|
||||
name: x,
|
||||
localId: null // same here
|
||||
}
|
||||
|
@ -52,7 +74,7 @@ module Helpers {
|
|||
export function mkExprHolder(defs: J.JLocalDef[], toks: J.JToken[]): J.JExprHolder {
|
||||
return {
|
||||
nodeType: "exprHolder",
|
||||
id: "TODO",
|
||||
id: null,
|
||||
tokens: toks,
|
||||
tree: null,
|
||||
locals: defs,
|
||||
|
@ -63,7 +85,7 @@ module Helpers {
|
|||
export function mkExprStmt(expr: J.JExpr): J.JStmt {
|
||||
return {
|
||||
nodeType: "exprStmt",
|
||||
id: "TODO",
|
||||
id: null,
|
||||
expr: expr,
|
||||
};
|
||||
}
|
||||
|
@ -71,12 +93,45 @@ module Helpers {
|
|||
export function mkWhile(condition: J.JToken[], body: J.JStmt[]): J.JStmt {
|
||||
return {
|
||||
nodeType: "while",
|
||||
id: "TODO",
|
||||
id: null,
|
||||
condition: mkExprHolder([], condition),
|
||||
body: body
|
||||
};
|
||||
}
|
||||
|
||||
export function mkSimpleIf(condition: J.JToken[], thenBranch: J.JStmt[]): J.JIf {
|
||||
return {
|
||||
nodeType: "if",
|
||||
id: null,
|
||||
condition: mkExprHolder([], condition),
|
||||
thenBody: thenBranch,
|
||||
elseBody: null,
|
||||
isElseIf: false,
|
||||
};
|
||||
}
|
||||
|
||||
// This function takes care of generating an if node *and* de-constructing the
|
||||
// else branch to abide by the TouchDevelop representation (see comments in
|
||||
// [jsonInterfaces.ts]).
|
||||
export function mkIf(condition: J.JToken[], thenBranch: J.JStmt[], elseBranch: J.JStmt[]): J.JIf[] {
|
||||
var ifNode = mkSimpleIf(condition, thenBranch)
|
||||
|
||||
// The transformation into a "flat" if / else if / else sequence is only
|
||||
// valid if the else branch it itself such a sequence.
|
||||
var fitForFlattening = elseBranch.length && elseBranch.every((s: J.JStmt, i: number) =>
|
||||
s.nodeType == "if" && (i == 0 || (<J.JIf> s).isElseIf)
|
||||
);
|
||||
if (fitForFlattening) {
|
||||
var first = <J.JIf> elseBranch[0];
|
||||
assert(!first.isElseIf);
|
||||
first.isElseIf = true;
|
||||
return [ifNode].concat(<J.JIf[]> elseBranch);
|
||||
} else {
|
||||
ifNode.elseBody = elseBranch;
|
||||
return [ifNode];
|
||||
}
|
||||
}
|
||||
|
||||
// Generate the AST for:
|
||||
// [var x: t := e]
|
||||
export function mkDefAndAssign(x: string, t: string, e: J.JToken[]): J.JStmt {
|
||||
|
@ -92,7 +147,7 @@ module Helpers {
|
|||
export function mkAction(name: string, body: J.JStmt[]): J.JAction {
|
||||
return {
|
||||
nodeType: "action",
|
||||
id: "TODO",
|
||||
id: null,
|
||||
name: name,
|
||||
body: body,
|
||||
inParameters: [],
|
||||
|
@ -106,10 +161,10 @@ module Helpers {
|
|||
};
|
||||
}
|
||||
|
||||
export function mkApp(name: string, description: string, actions: J.JAction[]) {
|
||||
export function mkApp(name: string, description: string, actions: J.JAction[]): J.JApp {
|
||||
return {
|
||||
nodeType: "app",
|
||||
id: "TODO",
|
||||
id: null,
|
||||
|
||||
textVersion: "v2.2,js,ctx,refs,localcloud,unicodemodel,allasync,upperplex",
|
||||
jsonVersion: "v0.1,resolved",
|
||||
|
@ -148,29 +203,44 @@ interface Expr {
|
|||
prec: number;
|
||||
}
|
||||
|
||||
function compileNumber(b: B.Block): J.JOperator[] {
|
||||
function compileNumber(b: B.Block): Expr {
|
||||
var n = b.getFieldValue("NUM")+"";
|
||||
var toks: J.JOperator[] = [];
|
||||
for (var i = 0; i < n.length; ++i)
|
||||
toks.push(Helpers.mkOp(n[i]));
|
||||
return toks;
|
||||
return {
|
||||
tokens: toks,
|
||||
prec: 0
|
||||
};
|
||||
}
|
||||
|
||||
// 0 is for atomic tokens
|
||||
var precedenceTable: { [index: string]: number } = {
|
||||
"*": 1,
|
||||
"/": 1,
|
||||
"+": 2,
|
||||
"-": 2,
|
||||
"<": 3,
|
||||
"<=": 3,
|
||||
">": 3,
|
||||
">=": 3,
|
||||
"=": 4,
|
||||
"!=": 4,
|
||||
};
|
||||
|
||||
// Convert a blockly "OP" field into a TouchDevelop operator.
|
||||
// TODO: unary minus, power
|
||||
var opToTok: { [index: string]: string } = {
|
||||
"ADD": "+",
|
||||
"MINUS": "-",
|
||||
"MULTIPLY": "*",
|
||||
"DIVIDE": "/",
|
||||
"POWER": "",
|
||||
//"POWER": "", // TODO
|
||||
"EQ": "=",
|
||||
"NEQ": "!=",
|
||||
"LT": "<",
|
||||
"LTE": "<=",
|
||||
"GT": ">",
|
||||
"GTE": ">=",
|
||||
};
|
||||
|
||||
function wrapParentheses(e: J.JToken[]): J.JToken[] {
|
||||
|
@ -179,8 +249,6 @@ function wrapParentheses(e: J.JToken[]): J.JToken[] {
|
|||
|
||||
function compileArithmetic(b: B.Block): Expr {
|
||||
var bOp = b.getFieldValue("OP");
|
||||
if (bOp == "POWER")
|
||||
throw "TODO";
|
||||
var prec = precedenceTable[opToTok[bOp]];
|
||||
var op = Helpers.mkOp(opToTok[bOp]);
|
||||
var left = compileExpression(b.getInputTargetBlock("A"));
|
||||
|
@ -194,15 +262,31 @@ function compileArithmetic(b: B.Block): Expr {
|
|||
};
|
||||
}
|
||||
|
||||
function compileVariableGet(b: B.Block): Expr {
|
||||
return {
|
||||
tokens: [Helpers.mkLocalRef(b.getFieldValue("VAR"))],
|
||||
prec: 0
|
||||
};
|
||||
}
|
||||
|
||||
function compileText(b: B.Block): Expr {
|
||||
return {
|
||||
tokens: [Helpers.mkStringLiteral(b.getFieldValue("TEXT"))],
|
||||
prec: 0
|
||||
};
|
||||
}
|
||||
|
||||
function compileExpression(b: B.Block): Expr {
|
||||
switch (b.type) {
|
||||
case "math_number":
|
||||
return {
|
||||
tokens: compileNumber(b),
|
||||
prec: 0
|
||||
};
|
||||
return compileNumber(b);
|
||||
case "math_arithmetic":
|
||||
case "logic_compare":
|
||||
return compileArithmetic(b);
|
||||
case "variables_get":
|
||||
return compileVariableGet(b);
|
||||
case "text":
|
||||
return compileText(b);
|
||||
}
|
||||
throw (b.type + " is not an expression block or is not supported");
|
||||
// unreachable
|
||||
|
@ -213,8 +297,19 @@ function compileExpression(b: B.Block): Expr {
|
|||
// Statements
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
function compileControlsIf(b: B.ControlsIfBlock): J.JStmt {
|
||||
throw "Not implemented";
|
||||
function compileControlsIf(b: B.ControlsIfBlock): J.JStmt[] {
|
||||
var stmts: J.JIf[] = [];
|
||||
for (var i = 0; i <= b.elseifCount_; ++i) {
|
||||
var cond = compileExpression(b.getInputTargetBlock("IF"+i)).tokens;
|
||||
var thenBranch = compileStatements(b.getInputTargetBlock("DO"+i));
|
||||
stmts.push(Helpers.mkSimpleIf(cond, thenBranch));
|
||||
if (i > 0)
|
||||
stmts[stmts.length - 1].isElseIf = true;
|
||||
}
|
||||
if (b.elseCount_) {
|
||||
stmts[stmts.length - 1].elseBody = compileStatements(b.getInputTargetBlock("ELSE"));
|
||||
}
|
||||
return stmts;
|
||||
}
|
||||
|
||||
function compileControlsFor(b: B.Block): J.JStmt[] {
|
||||
|
@ -249,18 +344,30 @@ function compileControlsFor(b: B.Block): J.JStmt[] {
|
|||
];
|
||||
}
|
||||
|
||||
function compilePrint(b: B.Block): J.JStmt {
|
||||
var text = compileExpression(b.getInputTargetBlock("TEXT")).tokens;
|
||||
var tokens = text.concat([
|
||||
Helpers.mkPropertyRef("post to wall"),
|
||||
]);
|
||||
return Helpers.mkExprStmt(Helpers.mkExprHolder([], tokens));
|
||||
}
|
||||
|
||||
function compileStatements(b: B.Block): J.JStmt[] {
|
||||
var stmts: J.JStmt[] = [];
|
||||
while (b) {
|
||||
switch (b.type) {
|
||||
case 'controls_if':
|
||||
// stmts.push(compileControlsIf(<B.ControlsIfBlock> b));
|
||||
stmts = stmts.concat(compileControlsIf(<B.ControlsIfBlock> b));
|
||||
break;
|
||||
|
||||
case 'controls_for':
|
||||
stmts = stmts.concat(compileControlsFor(b));
|
||||
break;
|
||||
|
||||
case 'text_print':
|
||||
stmts.push(compilePrint(b));
|
||||
break;
|
||||
|
||||
default:
|
||||
throw (b.type + " is not a statement block or is not supported");
|
||||
}
|
||||
|
|
Загрузка…
Ссылка в новой задаче