diff --git a/frege-interpreter-core/src/main/frege/frege/interpreter/FregeInterpreter.fr b/frege-interpreter-core/src/main/frege/frege/interpreter/FregeInterpreter.fr index d67231f..d432dc3 100644 --- a/frege-interpreter-core/src/main/frege/frege/interpreter/FregeInterpreter.fr +++ b/frege-interpreter-core/src/main/frege/frege/interpreter/FregeInterpreter.fr @@ -290,11 +290,9 @@ symbolClass symbol g = g.unpack symbol.name.getpack * until one of them returns an error -} run src predefs steps = do - g <- getST - let scriptType = findScriptType src + let scriptType = findSourceType src predefs varName = findUnusedVariableName (predefs ++ src) source = buildScript src scriptType predefs "Console" varName - changeST $ const g changeST Global.{gen <- GenSt.{printer=IO.stdout}} -- just to have no undefined value there foreach (steps source) runpass g <- getST @@ -306,6 +304,35 @@ run src predefs steps = do sym = fst $ StG.run (resolveSymbol varName) g else return Nothing +findSourceType :: String -> String -> SourceType +findSourceType src predefs = + case calcSourceType src of + Just ModuleSource -> SourceType.ModuleSource + Just ExpressionSource -> SourceType.ExpressionSource + otherwise -> case calcSourceType (buildScript src SourceType.DefinitionsSource predefs "T" "") of + Just ModuleSource -> SourceType.DefinitionsSource + _ -> SourceType.ExpressionSource + where + calcSourceType src = fst $ StG.run (calculateSourceTypeST src) env + env = interpreterCompilerEnv InterpreterClassLoader.default + +calculateSourceTypeST :: String -> StG (Maybe SourceType) +calculateSourceTypeST src = do + g <- getST + pw <- doio $ StringWriter.new () >>= StringWriter.printer + changeST Global.{sub <- SubSt.{stderr=pw}} + runpass (lexPass src, "lexical analysis ", postTrue) + g <- getST + if g.errors != 0 + then return Nothing + else do + let tokens = filter noDocComment g.sub.toks.toList + result <- Parse.pass tokens + case result of + Nothing -> return Nothing + Just (GUtil.Program.Module _) -> return (Just SourceType.ModuleSource) + _ -> return (Just SourceType.ExpressionSource) + {- Compiler state with interpreter options There is no IO; The classes are loaded in memory. @@ -371,27 +398,6 @@ instance Show SourceInfo where show (Expression _) = "Expression" show (Definitions _) = "Definitions" -findScriptType :: String -> SourceType -findScriptType src = fst $ StG.run f (interpreterCompilerEnv InterpreterClassLoader.default) where - f = do - runpass (lexPass src, "lexical analysis ", postTrue) - g <- getST - if g.errors == 0 - then scriptTypePass src - else return SourceType.ModuleSource - -scriptTypePass src = do - g <- getST - let tokens = filter noDocComment g.sub.toks.toList - case tokens of - [] -> return SourceType.ModuleSource - (Token{tokid=PACKAGE}) : _ -> return SourceType.ModuleSource - _ -> do - isDef <- isDefinition src - if isDef - then return SourceType.DefinitionsSource - else return SourceType.ExpressionSource - noDocComment Token{tokid} = tokid != COMMENT && tokid != DOCUMENTATION moduleDeclScript moduleName = "module " ++ moduleName ++ " where" @@ -571,23 +577,6 @@ iparsePass f = do indent n src = (unlines . map (spaces ++) . lines $ src) where spaces = concat $ replicate n " " -isDefinition :: String -> StG Bool -isDefinition src = do - g <- getST - sw <- doio $ StringWriter.new () - pw <- doio $ sw.printer - let modDecl = intercalate newLine ["module T where", src] - changeST Global.{sub <- SubSt.{stderr=pw}} - runpass (lexPass modDecl, "lexical analysis ", postTrue) - g <- getST - if g.errors != 0 - then return false - else do - let tokens = filter noDocComment g.sub.toks.toList - result <- Parse.pass tokens - g <- getST - return $ g.errors == 0 - lexPass src = do changeST Global.{sub <- SubSt.{toks = arrayFromList []} . SubSt.{definitions = []} diff --git a/frege-script-engine/src/test/java/frege/scriptengine/FregeScriptEngineTest.java b/frege-script-engine/src/test/java/frege/scriptengine/FregeScriptEngineTest.java index 648dbce..09e3a8b 100644 --- a/frege-script-engine/src/test/java/frege/scriptengine/FregeScriptEngineTest.java +++ b/frege-script-engine/src/test/java/frege/scriptengine/FregeScriptEngineTest.java @@ -7,7 +7,11 @@ import javax.script.ScriptException; import org.junit.Before; +import org.junit.Rule; import org.junit.Test; +import org.junit.rules.TestRule; +import org.junit.rules.TestWatcher; +import org.junit.runner.Description; import java.math.BigInteger; @@ -93,4 +97,29 @@ public void testUnpackagedModule() throws ScriptException { final Object expected = "I am bar"; assertEquals(expected, actual); } + + @Test + public void testOperators() throws ScriptException { + frege.eval("infix 1 `³`"); + frege.eval("(x³) = x^3"); + final Object expected = frege.eval("(2³)"); + final Object actual = 8; + assertEquals(expected, actual); + } + + @Test + public void testImportOperators() throws ScriptException { + frege.eval("import Data.Monoid"); + frege.eval("import frege.data.wrapper.Num"); + final Object expected = frege.eval("Sum.unwrap $ Sum 1 <> Sum 0"); + final Object actual = 1; + assertEquals(expected, actual); + } + + @Test + public void testTypeAnnotation() throws ScriptException { + final Object expected = frege.eval("(one :: Int)"); + final Object actual = 1; + assertEquals(expected, actual); + } } diff --git a/pom.xml b/pom.xml index e13add7..300a5de 100644 --- a/pom.xml +++ b/pom.xml @@ -98,7 +98,7 @@ junit junit - 3.8.1 + 4.12 test