diff --git a/README.md b/README.md index acc6c0c..968f69f 100644 --- a/README.md +++ b/README.md @@ -76,12 +76,12 @@ npm test [MySQL](https://github.com/ajlopez/CobolScript/tree/master/samples/mysql) Connecting and using a MySQL server. +[MySQL Web](https://github.com/ajlopez/CobolScript/tree/master/samples/mysqlweb) Connecting and using a MySQL server, generating web pages. + ## To do - More Samples - Web Site with templates and layout, get and post processing -- explicit `stop run`. -- `exit`, `exit perform`. - File section. - Pictures. - `exec sql`. diff --git a/lib/cobolscript.js b/lib/cobolscript.js index 35ce0a1..9510ec8 100644 --- a/lib/cobolscript.js +++ b/lib/cobolscript.js @@ -268,10 +268,20 @@ var cobolscript = (function () { var variable = new VariableExpression(name); this.compile = function(program, context) { - var code = variable.compile(program, context); - code += '['; + var code = 'runtime.getIndex(' + variable.compile(program, context); + code += ', '; code += index.compile(program, context); - code += ']'; + code += ')'; + return code; + } + + this.compileSet = function(program, context, value) { + var code = 'runtime.setIndex(' + variable.compile(program, context); + code += ', '; + code += index.compile(program, context); + code += ', '; + code += value; + code += ')'; return code; } } function VariableExpression(name) { name = normalizeName(name); @@ -535,7 +545,7 @@ var cobolscript = (function () { oper = '>='; } - code = 'for (' + forvariable + ' = ' + options.from.compile(program, context) + '; ' + forvariable + ' ' + oper + ' ' + options.to.compile(program) + '; ' + forvariable + ' ' + incr + ')'; + code = 'for (' + forvariable + ' = ' + options.from.compile(program, context) + '; ' + forvariable + ' ' + oper + ' ' + options.to.compile(program, context) + '; ' + forvariable + ' ' + incr + ')'; } else { code = 'while ('; @@ -610,7 +620,7 @@ var cobolscript = (function () { oper = '>='; } - code = 'for (' + forvariable + ' = ' + options.from.compile(program, context) + '; ' + forvariable + ' ' + oper + ' ' + options.to.compile(program) + '; ' + forvariable + incr + ') ' + code; + code = 'for (' + forvariable + ' = ' + options.from.compile(program, context) + '; ' + forvariable + ' ' + oper + ' ' + options.to.compile(program, context) + '; ' + forvariable + incr + ') ' + code; } else if (!options.async && options.giving) { if (!(options.giving instanceof Array)) { @@ -768,8 +778,20 @@ var cobolscript = (function () { variables = variable; } else { variables = [ variable ]; - } this.compile = function(program, context) { var code = '', n = variables.length; for (var k = 0; k < n; k++) { code = code + variables[k].compile(program, context) + ' = '; - } code += expr.compile(program, context) + ';'; return code; }; }; function BinaryToCommand(expr, variable, oper, giving, from) { + } this.compile = function(program, context) { var code, n = variables.length; + var exprcode = expr.compile(program, context); + + if (n == 1) + if (variables[0].compileSet) + return variables[0].compileSet(program, context, exprcode) + ';'; + else + return variables[0].compile(program, context) + ' = ' + exprcode + ';'; + + code = 'var $aux = ' + exprcode + ';'; for (var k = 0; k < n; k++) + if (variables[k].compileSet) + code = code + ' ' + variables[k].compileSet(program, context, '$aux') + ';'; + else code = code + ' ' + variables[k].compile(program, context) + ' = $aux;'; + return code; }; }; function BinaryToCommand(expr, variable, oper, giving, from) { if (expr instanceof Array && expr.length === 1) { expr = expr[0]; } @@ -799,25 +821,42 @@ var cobolscript = (function () { for (var k = 0; k < n; k++) { if (!giving) { - code += variable[k].compile(program, context) + ' ' + oper + '= $aux;'; + if (variable[k].compileSet) + code += variable[k].compileSet(program, context, variable[k].compile(program, context) + ' ' + oper + ' $aux') + ';' + else + code += variable[k].compile(program, context) + ' ' + oper + '= $aux;'; } else { - code += variable[k].compile(program, context) + ' = $aux;'; + if (variable[k].compileSet) + code += variable[k].compileSet(program, context, '$aux') + ';'; + else + code += variable[k].compile(program, context) + ' = $aux;'; } } return code; }; function compileTarget(program, context, target) { - var code = target.compile(program, context) + ' = '; + var exprcode = compileExpression(program, context); + var targetcode = target.compile(program, context); + var code; + + if (target.compileSet) { + if (oper === '=') + return target.compileSet(program, context, exprcode); + var suboper = oper[0]; + return target.compileSet(program, context, targetcode + ' ' + suboper + ' ' + exprcode); + } + + code = targetcode + ' = '; if (!giving) { - code += target.compile(program, context) + ' ' + oper + ' '; + code += targetcode + ' ' + oper + ' '; } else if (from) { code += from.compile(program, context) + ' ' + oper + ' '; } - code += compileExpression(program, context) + ';'; + code += exprcode + ';'; return code; }; @@ -1679,6 +1718,22 @@ var cobolscript = (function () { this.flush(); process.exit(value); }; + + function getIndex(obj, index) { + if (typeof index == 'number') + return obj[index - 1]; + return obj[index]; + } + + function setIndex(obj, index, value) { + if (typeof index == 'number') + obj[index - 1] = value; + else + obj[index] = value; + } + + Runtime.prototype.getIndex = getIndex; + Runtime.prototype.setIndex = setIndex; function WebRuntime(request, response) { @@ -1714,6 +1769,9 @@ var cobolscript = (function () { WebRuntime.prototype.stop = function(value) { this.flush(); }; + + WebRuntime.prototype.getIndex = getIndex; + WebRuntime.prototype.setIndex = setIndex; function getRuntime(options) { var runtime; diff --git a/samples/mysql/README.md b/samples/mysql/README.md new file mode 100644 index 0000000..a46f0f5 --- /dev/null +++ b/samples/mysql/README.md @@ -0,0 +1,55 @@ +# MySQL Sample + +CobolScript can access MySQL server using a Node.js module. + +## Setup + +Install [Node.js](http://nodejs.org). + +Then, execute at command line: +``` +npm install +``` + +This command installs the `mysql` module, according to the dependecies described in `package.json` file. + +## Run + +With the command line: +``` +node run showdb.cob +``` + +The program connects to the MySQL server at localhost and list its database. The server must be running. + +The code +``` +perform require using "mysql" giving mysql. +``` +loads the `mysql` module. + +Then +``` +local options. + +move object to options. +move "root" to user in options. +move "" to password in options. + +local connection. + +perform createConnection in mysql using options giving connection. +``` +opens the connection. + +The code +``` +perform query in connection using "show databases" showdbs. + +showdbs section using err, rows, fields. +* .... +``` +pass `showdbs` as a callback to asynchronous method `query` in `connection`. The callbacks accept three parameters. + + + diff --git a/samples/mysql/showdb.cob b/samples/mysql/showdb.cob index 85daca8..4a0b84e 100644 --- a/samples/mysql/showdb.cob +++ b/samples/mysql/showdb.cob @@ -1 +1 @@ -data division. linkage section. 01 global. 01 require. procedure division. local mysql. perform require using "mysql" giving mysql. local options. move object to options. move "root" to user in options. move "" to password in options. local connection. perform createConnection in mysql using options giving connection. perform query in connection using "show databases" showdbs. showdbs section using err, rows, fields. if err then display err stop run end-if. local k. local n. move length in rows to n. move 0 to k. local row. perform until k >= n if k < n then move rows(k) to row display Database in row end-if add 1 to k end-perform. stop run. \ No newline at end of file +data division. linkage section. 01 global. 01 require. procedure division. local mysql. perform require using "mysql" giving mysql. local options. move object to options. move "root" to user in options. move "" to password in options. local connection. perform createConnection in mysql using options giving connection. perform query in connection using "show databases" showdbs. showdbs section using err, rows, fields. if err then display err stop run end-if. local k. local n. move length in rows to n. local row. perform varying k from 1 to n move rows(k) to row display Database in row end-perform. stop run. \ No newline at end of file diff --git a/samples/mysqlweb/databases.cobp b/samples/mysqlweb/databases.cobp index baa6605..1b79221 100644 --- a/samples/mysqlweb/databases.cobp +++ b/samples/mysqlweb/databases.cobp @@ -38,14 +38,13 @@ move length in rows to n. move 0 to k. local row. -perform until k >= n +perform varying k from 1 to n move rows(k) to row #> ${Database in row} <# - add 1 to k end-perform #> diff --git a/test/compile.js b/test/compile.js index e375820..aae58b8 100644 --- a/test/compile.js +++ b/test/compile.js @@ -127,7 +127,7 @@ assert.ok(text.indexOf('ws.a_2 = 2;') >= 0); var text = compile('move 1 to a-1, a-2.', { a_1: null, a_2: null }); assert.ok(text); -assert.ok(text.indexOf('ws.a_1 = ws.a_2 = 1;') >= 0); +assert.ok(text.indexOf('var $aux = 1; ws.a_1 = $aux; ws.a_2 = $aux;') >= 0); // simple function @@ -315,7 +315,7 @@ assert.ok(text.indexOf('a = [];') >= 0); // move to an indexed array by name var text = compile('local a. move 1 to a("foo")'); -assert.ok(text.indexOf('a["foo"] = 1;') >= 0); +assert.ok(text.indexOf('runtime.setIndex(a, "foo", 1);') >= 0); // perform with async @@ -358,6 +358,9 @@ assert.equal(text, 'var a; a = 1; while (true) { a = a + 1; if (!(a > 10)) break var text = compile('local a. local k. move 0 to a. perform varying k from 1 to 10 add k to a end-perform.'); assert.equal(text, 'var a; var k; a = 0; for (k = 1; k <= 10; k += 1) { a = a + k; }'); +var text = compile('local a. local k. local n. move 0 to a. move 10 to n. perform varying k from 1 to n add k to a end-perform.'); +assert.equal(text, 'var a; var k; var n; a = 0; n = 10; for (k = 1; k <= n; k += 1) { a = a + k; }'); + // stop run var text = compile('stop run.'); diff --git a/test/perform.js b/test/perform.js index d20c599..be3c037 100644 --- a/test/perform.js +++ b/test/perform.js @@ -10,7 +10,7 @@ function run(text, ws) { program.data.working_storage = ws; } - return program.compileFunction(program)(null, program); + return program.compileFunction(program)(cobs.getRuntime(), program); }; // perform procedure @@ -106,10 +106,23 @@ run('local k. move 0 to result. perform varying k from 1 to 4 add k to result en assert.ok(ws.result); assert.equal(ws.result, 10); -// perform inline perform +// perform inline perform with exit perform var ws = { result: null }; run('local k. move 0 to result. perform varying k from 1 to 4 add k to result if k >= 3 then exit perform end-perform.', ws); assert.ok(ws.result); assert.equal(ws.result, 6); +// perform inline perform setting array values + +var ws = { a: [1, 2, 3, 4] }; +run('local k. perform varying k from 1 to 4 add 1 to a(k) end-perform.', ws); +assert.ok(ws.a); +assert.equal(ws.a.toString(), '2,3,4,5'); + +var ws = { a: [0, 0, 0, 0], b: [0, 0, 0, 0] }; +run('local k. perform varying k from 1 to 4 move k to a(k) b(k) end-perform.', ws); +assert.ok(ws.a); +assert.equal(ws.a.toString(), '1,2,3,4'); +assert.ok(ws.b); +assert.equal(ws.b.toString(), '1,2,3,4'); diff --git a/test/runtime.js b/test/runtime.js index 3903dea..57cebb0 100644 --- a/test/runtime.js +++ b/test/runtime.js @@ -18,6 +18,10 @@ assert.ok(runtime.write); assert.equal(typeof(runtime.write), 'function'); assert.ok(runtime.flush); assert.equal(typeof(runtime.flush), 'function'); +assert.ok(runtime.getIndex); +assert.equal(typeof(runtime.getIndex), 'function'); +assert.ok(runtime.setIndex); +assert.equal(typeof(runtime.setIndex), 'function'); assert.ok(runtime.global); // getRuntime with response, request, require @@ -31,6 +35,10 @@ assert.ok(runtime.write); assert.equal(typeof(runtime.write), 'function'); assert.ok(runtime.flush); assert.equal(typeof(runtime.flush), 'function'); +assert.ok(runtime.getIndex); +assert.equal(typeof(runtime.getIndex), 'function'); +assert.ok(runtime.setIndex); +assert.equal(typeof(runtime.setIndex), 'function'); assert.ok(runtime.response); assert.ok(runtime.request); assert.ok(runtime.global);