|
@@ -16,18 +16,28 @@ var Arg = Class.extend({
|
|
|
});
|
|
|
exports.Arg = Arg;
|
|
|
|
|
|
+var CheckArgumentResult = Arg.extend({
|
|
|
+ init: function(type, isVar, convert){
|
|
|
+ Arg.prototype.init.call(this, type, isVar);
|
|
|
+ this.convert = convert;
|
|
|
+ }
|
|
|
+});
|
|
|
+
|
|
|
var ProcCallGenerator = Class.extend({
|
|
|
- init: function ProcCallGenerator(codeGenerator, id, type){
|
|
|
- this.__codeGenerator = codeGenerator;
|
|
|
+ init: function ProcCallGenerator(context, id, type){
|
|
|
+ this.__context = context;
|
|
|
this.__id = id;
|
|
|
this.__type = type;
|
|
|
this.__argumentsCount = 0;
|
|
|
+ this.__code = new Code.SimpleGenerator();
|
|
|
this.writeCode(this.prolog());
|
|
|
},
|
|
|
id: function(){return this.__id;},
|
|
|
+ codeGenerator: function(){return this.__code;},
|
|
|
handleArgument: function(type, designator, code){
|
|
|
var pos = this.__argumentsCount++;
|
|
|
var isVarArg = false;
|
|
|
+ var convert;
|
|
|
if (this.__type){
|
|
|
var expectedArguments = this.__type.arguments();
|
|
|
if (pos >= expectedArguments.length )
|
|
@@ -36,6 +46,7 @@ var ProcCallGenerator = Class.extend({
|
|
|
|
|
|
var arg = this.checkArgument(pos, type, designator);
|
|
|
isVarArg = arg.isVar;
|
|
|
+ convert = arg.convert;
|
|
|
}
|
|
|
if (designator){
|
|
|
var info = designator.info();
|
|
@@ -45,6 +56,10 @@ var ProcCallGenerator = Class.extend({
|
|
|
else if (!info.isVar() && isVarArg)
|
|
|
code = designator.refCode();
|
|
|
}
|
|
|
+
|
|
|
+ if (convert)
|
|
|
+ code = convert(code);
|
|
|
+
|
|
|
var prefix = pos ? ", " : "";
|
|
|
this.writeCode(prefix + code);
|
|
|
},
|
|
@@ -56,15 +71,21 @@ var ProcCallGenerator = Class.extend({
|
|
|
+ this.__argumentsCount);
|
|
|
}
|
|
|
this.writeCode(this.epilog());
|
|
|
- return this.__codeGenerator.result();
|
|
|
+ return this.codeGenerator().result();
|
|
|
},
|
|
|
prolog: function(){return this.__id + "(";},
|
|
|
checkArgument: function(pos, type, designator){
|
|
|
var arg = this.__type.arguments()[pos];
|
|
|
+ var convert;
|
|
|
var expectType = arg.type; // can be undefined for predefined functions (like NEW), dont check it in this case
|
|
|
if (expectType && !Cast.implicit(type, expectType))
|
|
|
- throw new Errors.Error("expect '" + expectType.name() + "' type for argument "
|
|
|
- + pos + ", got '" + type.name() + "'");
|
|
|
+ if (type instanceof Type.String && expectType instanceof Type.Array){
|
|
|
+ var rtl = this.__context.rtl();
|
|
|
+ convert = function(code){return rtl.strToArray(code);};
|
|
|
+ }
|
|
|
+ else
|
|
|
+ throw new Errors.Error("type mismatch for argument " + (pos + 1) + ": '" + type.description()
|
|
|
+ + "' cannot be converted to '" + expectType.description() + "'");
|
|
|
if (arg.isVar){
|
|
|
if (!designator)
|
|
|
throw new Errors.Error("expression cannot be used as VAR parameter");
|
|
@@ -74,10 +95,10 @@ var ProcCallGenerator = Class.extend({
|
|
|
if (info.isReadOnly())
|
|
|
throw new Errors.Error("read-only variable cannot be used as VAR parameter");
|
|
|
}
|
|
|
- return arg;
|
|
|
+ return new CheckArgumentResult(arg.type, arg.isVar, convert);
|
|
|
},
|
|
|
epilog: function(){return ")";},
|
|
|
- writeCode: function(s){this.__codeGenerator.write(s);}
|
|
|
+ writeCode: function(s){this.codeGenerator().write(s);}
|
|
|
});
|
|
|
|
|
|
var ProcType = Type.Basic.extend({
|
|
@@ -87,8 +108,8 @@ var ProcType = Type.Basic.extend({
|
|
|
this.__result = result;
|
|
|
this.__callGeneratorFactory = callGeneratorFactory
|
|
|
? callGeneratorFactory
|
|
|
- : function(codeGenerator, id, type){
|
|
|
- return new ProcCallGenerator(codeGenerator, id, type);
|
|
|
+ : function(context, id, type){
|
|
|
+ return new ProcCallGenerator(context, id, type);
|
|
|
};
|
|
|
},
|
|
|
isProcedure: function(){return true;},
|
|
@@ -105,8 +126,8 @@ var ProcType = Type.Basic.extend({
|
|
|
return 'PROCEDURE' + this.__dumpProcArgs()
|
|
|
+ (this.__result ? ": " + this.__result.name() : "");
|
|
|
},
|
|
|
- callGenerator: function(codeGenerator, id){
|
|
|
- return this.__callGeneratorFactory(codeGenerator, id, this);
|
|
|
+ callGenerator: function(context, id){
|
|
|
+ return this.__callGeneratorFactory(context, id, this);
|
|
|
},
|
|
|
__dumpProcArgs: function(){
|
|
|
if (!this.__arguments.length)
|
|
@@ -124,20 +145,21 @@ var ProcType = Type.Basic.extend({
|
|
|
});
|
|
|
|
|
|
var TwoArgToOperatorProcCallGenerator = ProcCallGenerator.extend({
|
|
|
- init: function TwoArgToOperatorProcCallGenerator(codeGenerator, id, type, operator){
|
|
|
- ProcCallGenerator.prototype.init.bind(this)(Code.nullGenerator, id, type);
|
|
|
- this.__code = codeGenerator;
|
|
|
+ init: function TwoArgToOperatorProcCallGenerator(context, id, type, operator){
|
|
|
+ ProcCallGenerator.prototype.init.call(this, context, id, type);
|
|
|
+ this.__code = context.codeGenerator();
|
|
|
this.__operator = operator;
|
|
|
this.__firstArgumentCode = undefined;
|
|
|
this.__secondArgumentCode = undefined;
|
|
|
},
|
|
|
+ codeGenerator: function(){return Code.nullGenerator;},
|
|
|
prolog: function(id){return "";},
|
|
|
handleArgument: function(type, designator, code){
|
|
|
if (!this.__firstArgumentCode)
|
|
|
this.__firstArgumentCode = code;
|
|
|
else
|
|
|
this.__secondArgumentCode = code;
|
|
|
- ProcCallGenerator.prototype.handleArgument.bind(this)(type, designator, code);
|
|
|
+ ProcCallGenerator.prototype.handleArgument.call(this, type, designator, code);
|
|
|
},
|
|
|
epilog: function(type){return "";},
|
|
|
end: function(){
|
|
@@ -148,18 +170,18 @@ var TwoArgToOperatorProcCallGenerator = ProcCallGenerator.extend({
|
|
|
exports.predefined = [
|
|
|
function(){
|
|
|
var NewProcCallGenerator = ProcCallGenerator.extend({
|
|
|
- init: function NewProcCallGenerator(codeGenerator, id, type){
|
|
|
- ProcCallGenerator.prototype.init.bind(this)(codeGenerator, id, type);
|
|
|
+ init: function NewProcCallGenerator(context, id, type){
|
|
|
+ ProcCallGenerator.prototype.init.call(this, context, id, type);
|
|
|
this.__baseType = undefined;
|
|
|
},
|
|
|
prolog: function(id){return "";},
|
|
|
checkArgument: function(pos, type, designator){
|
|
|
- ProcCallGenerator.prototype.checkArgument.bind(this)(pos, type, designator);
|
|
|
+ ProcCallGenerator.prototype.checkArgument.call(this, pos, type, designator);
|
|
|
if (!(type instanceof Type.Pointer))
|
|
|
throw new Errors.Error("POINTER variable expected, got '"
|
|
|
+ type.name() + "'");
|
|
|
this.__baseType = type.baseType();
|
|
|
- return new Arg(type, false);
|
|
|
+ return new CheckArgumentResult(type, false);
|
|
|
},
|
|
|
epilog: function(){return " = new " + this.__baseType.name() + "()";}
|
|
|
});
|
|
@@ -170,8 +192,8 @@ exports.predefined = [
|
|
|
"predefined procedure NEW",
|
|
|
args,
|
|
|
undefined,
|
|
|
- function(codeGenerator, id, type){
|
|
|
- return new NewProcCallGenerator(codeGenerator, id, type);
|
|
|
+ function(context, id, type){
|
|
|
+ return new NewProcCallGenerator(context, id, type);
|
|
|
}));
|
|
|
var symbol = new Type.Symbol(name, type);
|
|
|
return symbol;
|
|
@@ -184,9 +206,9 @@ exports.predefined = [
|
|
|
"predefined procedure INCL",
|
|
|
args,
|
|
|
undefined,
|
|
|
- function(codeGenerator, id, type){
|
|
|
+ function(context, id, type){
|
|
|
return new TwoArgToOperatorProcCallGenerator(
|
|
|
- codeGenerator, id, type, operator);
|
|
|
+ context, id, type, operator);
|
|
|
});
|
|
|
var type = new Type.Procedure(proc);
|
|
|
var symbol = new Type.Symbol("INCL", type);
|
|
@@ -200,9 +222,9 @@ exports.predefined = [
|
|
|
"predefined procedure EXCL",
|
|
|
args,
|
|
|
undefined,
|
|
|
- function(codeGenerator, id, type){
|
|
|
+ function(context, id, type){
|
|
|
return new TwoArgToOperatorProcCallGenerator(
|
|
|
- codeGenerator, id, type, operator);
|
|
|
+ context, id, type, operator);
|
|
|
});
|
|
|
var type = new Type.Procedure(proc);
|
|
|
var symbol = new Type.Symbol("EXCL", type);
|