Syntax editor: wrap now handles multiple possible positions for subtree

This commit is contained in:
john.j.camilleri
2012-12-04 15:45:41 +00:00
parent 01cdd10e07
commit 44138ff8ce
2 changed files with 37 additions and 12 deletions

View File

@@ -137,7 +137,8 @@ function AST(fun, cat) {
} }
// Wrap the current node inside another node // Wrap the current node inside another node
this.wrap = function(typeobj, childid) { // Doesn't check whether child_id is within in range
this.wrap = function(typeobj, child_id) {
var subtree = new ASTNode(this.currentNode); var subtree = new ASTNode(this.currentNode);
this.currentNode.fun = typeobj.name.join(" "); this.currentNode.fun = typeobj.name.join(" ");
this.currentNode.cat = typeobj.ret; this.currentNode.cat = typeobj.ret;
@@ -145,7 +146,7 @@ function AST(fun, cat) {
for (var i in typeobj.args) { for (var i in typeobj.args) {
this.add(null, typeobj.args[i]); this.add(null, typeobj.args[i]);
} }
this.currentNode.children[i] = subtree; this.currentNode.children[child_id] = subtree;
return subtree; return subtree;
} }

View File

@@ -142,18 +142,23 @@ Editor.prototype.start_fresh=function () {
/* --- Functions for handling tree manipulation ----------------------------- */ /* --- Functions for handling tree manipulation ----------------------------- */
// Add refinement to UI, with a given callback function
Editor.prototype.add_refinement=function(t,fun,callback,disable_destructive) { // The opts param is used both in this function as:
// opts.disable_destructive
// as well as being passed to the callback function
Editor.prototype.add_refinement=function(t,fun,callback,opts) {
// var t = this; // var t = this;
if (!opts) opts = {};
// hide refinement if identical to current fun? // hide refinement if identical to current fun?
var opt = span_class("refinement", text(fun)); var opt = span_class("refinement", text(fun));
opt.onclick = bind(function(){ opt.onclick = bind(function(){
callback(this.innerHTML) callback(opts);
}, opt); }, opt);
// If refinement would be destructive, disable it // If refinement would be destructive, disable it
if (disable_destructive) { if (opts.disable_destructive) {
var blank = t.ast.is_writable(); var blank = t.ast.is_writable();
var typeobj = t.lookup_fun(fun); var typeobj = t.lookup_fun(fun);
var inplace = t.ast.fits_in_place(typeobj); var inplace = t.ast.fits_in_place(typeobj);
@@ -179,7 +184,10 @@ Editor.prototype.get_refinements=function(cat) {
clear(t.ui.refinements); clear(t.ui.refinements);
for (var pi in data.producers) { for (var pi in data.producers) {
var fun = data.producers[pi]; var fun = data.producers[pi];
t.add_refinement(t, fun, bind(t.select_refinement,t), true); t.add_refinement(t, fun, bind(t.select_refinement,t), {
fun: fun,
disable_destructive: true
});
} }
}; };
var err = function(data){ var err = function(data){
@@ -193,8 +201,9 @@ Editor.prototype.get_refinements=function(cat) {
// Case 1: current node is blank/no kids // Case 1: current node is blank/no kids
// Case 2: kids have all same types, perform an in-place replacement // Case 2: kids have all same types, perform an in-place replacement
// Case 3: kids have diff types/number, prevent replacement (must clear first) // Case 3: kids have diff types/number, prevent replacement (must clear first)
Editor.prototype.select_refinement=function(fun) { Editor.prototype.select_refinement=function(opts) {
var t = this; var t = this;
var fun = opts.fun;
// Check if current node is blank or childless (case 1) // Check if current node is blank or childless (case 1)
var blank = t.ast.is_writable(); var blank = t.ast.is_writable();
@@ -281,19 +290,34 @@ Editor.prototype.wrap_candidates = function() {
t.ui.refinements.innerHTML = "Wrap with: "; t.ui.refinements.innerHTML = "Wrap with: ";
for (var i in refinements) { for (var i in refinements) {
var fun = refinements[i].name; var typeobj = refinements[i];
t.add_refinement(t, fun, bind(t.wrap,t), false); // t.add_refinement(t, typeobj.name, bind(t.wrap,t), false);
// Show a refinement for each potential child position
for (var a in typeobj.args) {
var arg = typeobj.args[a];
if (arg == cat) {
var label = typeobj.name + " ?" + (parseInt(a)+1);
t.add_refinement(t, label, bind(t.wrap,t), {
fun: typeobj.name,
disable_destructive: false,
child_id: a
});
}
}
} }
} }
// Wrap the current node inside another function // Wrap the current node inside another function
Editor.prototype.wrap = function(fun,childid) { Editor.prototype.wrap = function(opts) {
var t = this; var t = this;
var fun = opts.fun;
var child_id = opts.child_id;
var typeobj = t.grammar_constructors.funs[fun]; var typeobj = t.grammar_constructors.funs[fun];
// do actual replacement // do actual replacement
t.ast.wrap(typeobj, childid); t.ast.wrap(typeobj, child_id);
// refresh stuff // refresh stuff
t.redraw_tree(); t.redraw_tree();