Browse Source

LEN supports STRING

Vladislav Folts 11 years ago
parent
commit
a920a6d18a

BIN
bin/compiled.zip


+ 22 - 0
src/eberon/EberonSymbols.ob

@@ -0,0 +1,22 @@
+MODULE EberonSymbols;
+IMPORT EberonString, JsMap, Procedure, Scope, Symbols, Types;
+
+PROCEDURE lenArgumentCheck(argType: Types.PType): BOOLEAN;
+    RETURN Procedure.lenArgumentCheck(argType) 
+        OR (argType = EberonString.string)
+END lenArgumentCheck;
+
+PROCEDURE makeStd*(): JsMap.Type;
+VAR 
+    proc: Symbols.PSymbol;
+    result: JsMap.Type;
+BEGIN
+    result := Scope.makeStdSymbols();
+    proc := Procedure.makeLen(lenArgumentCheck);
+    JsMap.put(result, proc.id(), proc);
+    
+    Scope.addSymbolForType(EberonString.string, result);
+    RETURN result
+END makeStd;
+
+END EberonSymbols.

+ 2 - 6
src/eberon/eberon_grammar.js

@@ -3,10 +3,9 @@
 var Cast = require("js/EberonCast.js");
 var Cast = require("js/EberonCast.js");
 var Context = require("context.js");
 var Context = require("context.js");
 var EbContext = require("eberon/eberon_context.js");
 var EbContext = require("eberon/eberon_context.js");
-var EberonString = require("js/EberonString.js");
 var Grammar = require("grammar.js");
 var Grammar = require("grammar.js");
 var Parser = require("parser.js");
 var Parser = require("parser.js");
-var Scope = require("js/Scope.js");
+var Symbols = require("js/EberonSymbols.js");
 
 
 var and = Parser.and;
 var and = Parser.and;
 var context = Parser.context;
 var context = Parser.context;
@@ -48,9 +47,6 @@ function makeFieldList(identdef, identList, type, formalParameters){
         Context.FieldListDeclaration);
         Context.FieldListDeclaration);
 }
 }
 
 
-var stdSymbols = Scope.makeStdSymbols();
-Scope.addSymbolForType(EberonString.string(), stdSymbols);
-
 exports.language = {
 exports.language = {
   grammar: Grammar.make(
   grammar: Grammar.make(
       makeDesignator,
       makeDesignator,
@@ -63,7 +59,7 @@ exports.language = {
       EbContext.Expression,
       EbContext.Expression,
       Grammar.reservedWords + " SELF SUPER"
       Grammar.reservedWords + " SELF SUPER"
       ),
       ),
-    stdSymbols: stdSymbols,
+    stdSymbols: Symbols.makeStd(),
     types: {
     types: {
         implicitCast: Cast.implicit
         implicitCast: Cast.implicit
     }
     }

+ 30 - 24
src/ob/Procedure.ob

@@ -25,6 +25,11 @@ TYPE
     END;
     END;
     PStdCall = POINTER TO StdCall;
     PStdCall = POINTER TO StdCall;
 
 
+    LenArgumentCheck = PROCEDURE(argType: Types.PType): BOOLEAN;
+    CallLen* = RECORD(StdCall)
+        check: LenArgumentCheck
+    END;
+
     CallGenerator* = RECORD
     CallGenerator* = RECORD
         PROCEDURE handleArgument(e: Code.PExpression);
         PROCEDURE handleArgument(e: Code.PExpression);
         PROCEDURE end(): Code.PExpression;
         PROCEDURE end(): Code.PExpression;
@@ -411,33 +416,35 @@ BEGIN
     RETURN makeSymbol(makeStd(JsString.make("NEW"), call))
     RETURN makeSymbol(makeStd(JsString.make("NEW"), call))
 END makeNew;
 END makeNew;
 
 
-PROCEDURE makeLen(): Symbols.PSymbol;
-    TYPE
-        CallImpl = RECORD(StdCall)
-        END;
-    VAR
-        call: POINTER TO CallImpl;
+PROCEDURE lenArgumentCheck*(argType: Types.PType): BOOLEAN;
+    RETURN (argType IS Types.PArray) OR (argType IS Types.PString)
+END lenArgumentCheck;
 
 
-    PROCEDURE CallImpl.make(args: JsArray.Type; cx: LanguageContext.Type): Code.PExpression;
-    VAR
-        arg: Code.PExpression;
-        argType: Types.PType;
-    BEGIN
-        arg := checkSingleArgument(args, SELF, cx.types());
-        argType := arg.type();
-        IF ~(argType IS Types.PArray) & ~(argType IS Types.PString) THEN
-            Errors.raise(JsString.concat(JsString.concat(
-                JsString.make("ARRAY or string is expected as an argument of LEN, got '"),
-                argType.description()),
-                JsString.make("'")));
-        END;
-        RETURN Code.makeSimpleExpression(
-            JsString.concat(arg.code(), JsString.make(".length")),
-            Types.basic.integer)
-    END CallImpl.make;
+PROCEDURE CallLen.make(args: JsArray.Type; cx: LanguageContext.Type): Code.PExpression;
+VAR
+    arg: Code.PExpression;
+    argType: Types.PType;
+BEGIN
+    arg := checkSingleArgument(args, SELF, cx.types());
+    argType := arg.type();
+    IF ~SELF.check(argType) THEN
+        Errors.raise(JsString.concat(JsString.concat(
+            JsString.make("ARRAY or string is expected as an argument of LEN, got '"),
+            argType.description()),
+            JsString.make("'")));
+    END;
+    RETURN Code.makeSimpleExpression(
+        JsString.concat(arg.code(), JsString.make(".length")),
+        Types.basic.integer)
+END CallLen.make;
+
+PROCEDURE makeLen*(check: LenArgumentCheck): Symbols.PSymbol;
+VAR
+    call: POINTER TO CallLen;
 BEGIN
 BEGIN
     NEW(call);
     NEW(call);
     initStdCall(call);
     initStdCall(call);
+    call.check := check;
     hasArgumentWithCustomType(call);
     hasArgumentWithCustomType(call);
     RETURN makeSymbol(makeStd(JsString.make("LEN"), call))
     RETURN makeSymbol(makeStd(JsString.make("LEN"), call))
 END makeLen;
 END makeLen;
@@ -1000,7 +1007,6 @@ END make;
 BEGIN
 BEGIN
     predefined := JsArray.make();
     predefined := JsArray.make();
     JsArray.add(predefined, makeNew());
     JsArray.add(predefined, makeNew());
-    JsArray.add(predefined, makeLen());
     JsArray.add(predefined, makeOdd());
     JsArray.add(predefined, makeOdd());
     JsArray.add(predefined, makeAssert());
     JsArray.add(predefined, makeAssert());
     JsArray.add(predefined, setBitImpl("INCL", inclOp));
     JsArray.add(predefined, setBitImpl("INCL", inclOp));

+ 15 - 0
src/oberon/OberonSymbols.ob

@@ -0,0 +1,15 @@
+MODULE OberonSymbols;
+IMPORT JsMap, Procedure, Scope, Symbols;
+
+PROCEDURE makeStd*(): JsMap.Type;
+VAR 
+    proc: Symbols.PSymbol;
+    result: JsMap.Type;
+BEGIN
+    result := Scope.makeStdSymbols();
+    proc := Procedure.makeLen(Procedure.lenArgumentCheck);
+    JsMap.put(result, proc.id(), proc);
+    RETURN result
+END makeStd;
+
+END OberonSymbols.

+ 2 - 2
src/oberon/oberon_grammar.js

@@ -5,7 +5,7 @@ var Context = require("context.js");
 var Grammar = require("grammar.js");
 var Grammar = require("grammar.js");
 var ObContext = require("oberon/oberon_context.js");
 var ObContext = require("oberon/oberon_context.js");
 var Parser = require("parser.js");
 var Parser = require("parser.js");
-var Scope = require("js/Scope.js");
+var Symbols = require("js/OberonSymbols.js");
 
 
 var and = Parser.and;
 var and = Parser.and;
 var context = Parser.context;
 var context = Parser.context;
@@ -45,7 +45,7 @@ exports.language = {
             Context.Expression,
             Context.Expression,
             Grammar.reservedWords
             Grammar.reservedWords
             ),
             ),
-    stdSymbols: Scope.makeStdSymbols(),
+    stdSymbols: Symbols.makeStd(),
     types: {
     types: {
         implicitCast: Cast.implicit
         implicitCast: Cast.implicit
     }
     }

+ 7 - 0
test/expected/eberon/string.js

@@ -1,3 +1,9 @@
+var RTL$ = {
+    assert: function (condition){
+        if (!condition)
+            throw new Error("assertion failed");
+    }
+};
 var m = function (){
 var m = function (){
 var s = '';var s1 = '';var s2 = '';
 var s = '';var s1 = '';var s2 = '';
 var b = false;
 var b = false;
@@ -12,4 +18,5 @@ b = s1 > s2;
 b = s1 <= s2;
 b = s1 <= s2;
 b = s1 >= s2;
 b = s1 >= s2;
 p1(s);
 p1(s);
+RTL$.assert(s.length == 0);
 }();
 }();

+ 1 - 0
test/input/eberon/string.ob

@@ -16,4 +16,5 @@ BEGIN
     b := s1 >= s2;
     b := s1 >= s2;
 
 
     p1(s);
     p1(s);
+    ASSERT(LEN(s) = 0);
 END m.
 END m.

+ 6 - 0
test/test_unit_eberon.js

@@ -197,5 +197,11 @@ exports.suite = {
             + "PROCEDURE pVar(VAR a: ARRAY OF CHAR): BOOLEAN; RETURN FALSE END pVar;"),
             + "PROCEDURE pVar(VAR a: ARRAY OF CHAR): BOOLEAN; RETURN FALSE END pVar;"),
     pass("p(s)"),
     pass("p(s)"),
     fail(["pVar(s)", "type mismatch for argument 1: cannot pass 'STRING' as VAR parameter of type 'ARRAY OF CHAR'"])
     fail(["pVar(s)", "type mismatch for argument 1: cannot pass 'STRING' as VAR parameter of type 'ARRAY OF CHAR'"])
+    ),
+"STRING LEN": testWithContext(
+    context(grammar.expression,
+            "VAR s: STRING;"),
+    pass("LEN(s)"),
+    fail()
     )
     )
 };
 };