Commit 525d723b authored by Kenton Varda's avatar Kenton Varda

Update benchmark for new union syntax.

parent 5986724f
...@@ -36,16 +36,16 @@ int32_t makeExpression(Expression::Builder exp, uint depth) { ...@@ -36,16 +36,16 @@ int32_t makeExpression(Expression::Builder exp, uint depth) {
if (fastRand(8) < depth) { if (fastRand(8) < depth) {
left = fastRand(128) + 1; left = fastRand(128) + 1;
exp.setLeftValue(left); exp.getLeft().setValue(left);
} else { } else {
left = makeExpression(exp.initLeftExpression(), depth + 1); left = makeExpression(exp.getLeft().initExpression(), depth + 1);
} }
if (fastRand(8) < depth) { if (fastRand(8) < depth) {
right = fastRand(128) + 1; right = fastRand(128) + 1;
exp.setRightValue(right); exp.getRight().setValue(right);
} else { } else {
right = makeExpression(exp.initRightExpression(), depth + 1); right = makeExpression(exp.getRight().initExpression(), depth + 1);
} }
switch (exp.getOp()) { switch (exp.getOp()) {
...@@ -66,21 +66,21 @@ int32_t makeExpression(Expression::Builder exp, uint depth) { ...@@ -66,21 +66,21 @@ int32_t makeExpression(Expression::Builder exp, uint depth) {
int32_t evaluateExpression(Expression::Reader exp) { int32_t evaluateExpression(Expression::Reader exp) {
int32_t left = 0, right = 0; int32_t left = 0, right = 0;
switch (exp.whichLeft()) { switch (exp.getLeft().which()) {
case Expression::Left::LEFT_VALUE: case Expression::Left::VALUE:
left = exp.getLeftValue(); left = exp.getLeft().getValue();
break; break;
case Expression::Left::LEFT_EXPRESSION: case Expression::Left::EXPRESSION:
left = evaluateExpression(exp.getLeftExpression()); left = evaluateExpression(exp.getLeft().getExpression());
break; break;
} }
switch (exp.whichRight()) { switch (exp.getRight().which()) {
case Expression::Right::RIGHT_VALUE: case Expression::Right::VALUE:
right = exp.getRightValue(); right = exp.getRight().getValue();
break; break;
case Expression::Right::RIGHT_EXPRESSION: case Expression::Right::EXPRESSION:
right = evaluateExpression(exp.getRightExpression()); right = evaluateExpression(exp.getRight().getExpression());
break; break;
} }
......
...@@ -32,13 +32,15 @@ enum Operation { ...@@ -32,13 +32,15 @@ enum Operation {
struct Expression { struct Expression {
op@0: Operation; op@0: Operation;
union left @1; left @1 union {
leftValue@2 in left: Int32; value@2: Int32;
leftExpression@3 in left: Expression; expression@3: Expression;
}
union right @4; right @4 union {
rightValue@5 in right: Int32; value@5: Int32;
rightExpression@6 in right: Expression; expression@6: Expression;
}
} }
struct EvaluationResult { struct EvaluationResult {
......
...@@ -21,7 +21,8 @@ executable capnpc ...@@ -21,7 +21,8 @@ executable capnpc
data-binary-ieee754, data-binary-ieee754,
filepath, filepath,
directory, directory,
syb syb,
transformers
ghc-options: -Wall -fno-warn-missing-signatures ghc-options: -Wall -fno-warn-missing-signatures
other-modules: other-modules:
Lexer, Lexer,
......
...@@ -29,6 +29,7 @@ import Token(Located(Located)) ...@@ -29,6 +29,7 @@ import Token(Located(Located))
import Parser(parseFile) import Parser(parseFile)
import qualified Data.Map as Map import qualified Data.Map as Map
import Data.Map((!)) import Data.Map((!))
import qualified Data.Set as Set
import qualified Data.List as List import qualified Data.List as List
import Data.Maybe(mapMaybe, fromMaybe) import Data.Maybe(mapMaybe, fromMaybe)
import Text.Parsec.Pos(SourcePos, newPos) import Text.Parsec.Pos(SourcePos, newPos)
...@@ -699,13 +700,13 @@ compileParam scope (name, typeExp, defaultValue) = do ...@@ -699,13 +700,13 @@ compileParam scope (name, typeExp, defaultValue) = do
Nothing -> return Nothing Nothing -> return Nothing
return (name, typeDesc, defaultDesc) return (name, typeDesc, defaultDesc)
compileFile name decls = compileFile name decls importMap =
feedback (\desc -> do feedback (\desc -> do
(members, memberMap, options, statements) <- compileChildDecls (DescFile desc) decls (members, memberMap, options, statements) <- compileChildDecls (DescFile desc) decls
requireNoDuplicateNames decls requireNoDuplicateNames decls
return FileDesc return FileDesc
{ fileName = name { fileName = name
, fileImports = [] , fileImports = Map.elems importMap
, fileAliases = [d | DescAlias d <- members] , fileAliases = [d | DescAlias d <- members]
, fileConstants = [d | DescConstant d <- members] , fileConstants = [d | DescConstant d <- members]
, fileEnums = [d | DescEnum d <- members] , fileEnums = [d | DescEnum d <- members]
...@@ -713,16 +714,49 @@ compileFile name decls = ...@@ -713,16 +714,49 @@ compileFile name decls =
, fileInterfaces = [d | DescInterface d <- members] , fileInterfaces = [d | DescInterface d <- members]
, fileOptions = options , fileOptions = options
, fileMemberMap = memberMap , fileMemberMap = memberMap
, fileImportMap = undefined , fileImportMap = importMap
, fileStatements = statements , fileStatements = statements
}) })
parseAndCompileFile filename text = result where dedup :: Ord a => [a] -> [a]
(decls, parseErrors) = parseFile filename text dedup = Set.toList . Set.fromList
-- Here we're doing the copmile step even if there were errors in parsing, and just combining
-- all the errors together. This may allow the user to fix more errors per compiler iteration, parseAndCompileFile :: Monad m
-- but it might also be confusing if a parse error causes a subsequent compile error, especially => FilePath -- Name of this file.
-- if the compile error ends up being on a line before the parse error (e.g. there's a parse -> String -- Content of this file.
-- error in a type definition, causing a not-defined error on a field trying to use that type). -> (String -> m (Either FileDesc String)) -- Callback to import other files.
-- TODO: Re-evaluate after getting some experience on whether this is annoing. -> m (Status FileDesc) -- Compiled file and/or errors.
result = statusAddErrors parseErrors (compileFile filename decls) parseAndCompileFile filename text importCallback = do
let (decls, parseErrors) = parseFile filename text
importNames = dedup $ concatMap declImports decls
doImport (Located pos name) = do
result <- importCallback name
case result of
Left desc -> return (succeed (name, desc))
Right err -> return
(makeError pos (printf "Couldn't import \"%s\": %s" name err))
importStatuses <- mapM doImport importNames
return (do
-- We are now in the Status monad.
-- Report errors from parsing.
-- We do the compile step even if there were errors in parsing, and just combine all the
-- errors together. This may allow the user to fix more errors per compiler iteration, but
-- it might also be confusing if a parse error causes a subsequent compile error,
-- especially if the compile error ends up being on a line before the parse error (e.g.
-- there's a parse error in a type definition, causing a not-defined error on a field
-- trying to use that type).
-- TODO: Re-evaluate after getting some experience on whether this is annoing.
Active () parseErrors
-- Report errors from imports.
-- Similar to the above, we're continuing with compiling even if imports fail, but the
-- problem above probably doesn't occur in this case since global imports usually appear
-- at the top of the file anyway. The only annoyance is seeing a long error log because
-- of one bad import.
imports <- doAll importStatuses
-- Compile the file!
compileFile filename decls $ Map.fromList imports)
...@@ -24,6 +24,7 @@ ...@@ -24,6 +24,7 @@
module Grammar where module Grammar where
import Token (Located) import Token (Located)
import Data.Maybe (maybeToList)
data DeclName = AbsoluteName (Located String) data DeclName = AbsoluteName (Located String)
| RelativeName (Located String) | RelativeName (Located String)
...@@ -31,9 +32,19 @@ data DeclName = AbsoluteName (Located String) ...@@ -31,9 +32,19 @@ data DeclName = AbsoluteName (Located String)
| MemberName DeclName (Located String) | MemberName DeclName (Located String)
deriving (Show) deriving (Show)
declNameImport :: DeclName -> Maybe (Located String)
declNameImport (AbsoluteName _) = Nothing
declNameImport (RelativeName _) = Nothing
declNameImport (ImportName s) = Just s
declNameImport (MemberName parent _) = declNameImport parent
data TypeExpression = TypeExpression DeclName [TypeExpression] data TypeExpression = TypeExpression DeclName [TypeExpression]
deriving (Show) deriving (Show)
typeImports :: TypeExpression -> [Located String]
typeImports (TypeExpression name params) =
maybeToList (declNameImport name) ++ concatMap typeImports params
data FieldValue = VoidFieldValue data FieldValue = VoidFieldValue
| BoolFieldValue Bool | BoolFieldValue Bool
| IntegerFieldValue Integer | IntegerFieldValue Integer
...@@ -71,3 +82,17 @@ declarationName (UnionDecl n _ _) = Just n ...@@ -71,3 +82,17 @@ declarationName (UnionDecl n _ _) = Just n
declarationName (InterfaceDecl n _) = Just n declarationName (InterfaceDecl n _) = Just n
declarationName (MethodDecl n _ _ _ _) = Just n declarationName (MethodDecl n _ _ _ _) = Just n
declarationName (OptionDecl _ _) = Nothing declarationName (OptionDecl _ _) = Nothing
declImports :: Declaration -> [Located String]
declImports (AliasDecl _ name) = maybeToList $ declNameImport name
declImports (ConstantDecl _ t _) = typeImports t
declImports (EnumDecl _ decls) = concatMap declImports decls
declImports (EnumValueDecl _ _ decls) = concatMap declImports decls
declImports (StructDecl _ decls) = concatMap declImports decls
declImports (FieldDecl _ _ t _) = typeImports t
declImports (UnionDecl _ _ decls) = concatMap declImports decls
declImports (InterfaceDecl _ decls) = concatMap declImports decls
declImports (MethodDecl _ _ params t decls) =
concat [paramsImports, typeImports t, concatMap declImports decls] where
paramsImports = concat [typeImports pt | (_, pt, _) <- params]
declImports (OptionDecl name _) = maybeToList $ declNameImport name
...@@ -27,9 +27,13 @@ import System.Environment ...@@ -27,9 +27,13 @@ import System.Environment
import System.Console.GetOpt import System.Console.GetOpt
import System.Exit(exitFailure, exitSuccess) import System.Exit(exitFailure, exitSuccess)
import System.IO(hPutStr, stderr) import System.IO(hPutStr, stderr)
import System.FilePath(takeDirectory) import System.FilePath(takeDirectory, combine)
import System.Directory(createDirectoryIfMissing, doesDirectoryExist) import System.Directory(createDirectoryIfMissing, doesDirectoryExist)
import Control.Monad import Control.Monad
import Control.Monad.IO.Class(liftIO)
import Control.Exception(IOException, catch)
import Control.Monad.Trans.State(StateT, state, modify, execStateT)
import Prelude hiding (catch)
import Compiler import Compiler
import Util(delimit) import Util(delimit)
import Text.Parsec.Pos import Text.Parsec.Pos
...@@ -96,35 +100,77 @@ main = do ...@@ -96,35 +100,77 @@ main = do
exitFailure) exitFailure)
mapM_ verifyDirectoryExists [dir | (_, dir) <- outputs] mapM_ verifyDirectoryExists [dir | (_, dir) <- outputs]
mapM_ (handleFile outputs isVerbose) files CompilerState failed _ <-
execStateT (mapM_ (handleFile outputs isVerbose) files) (CompilerState False Map.empty)
when failed exitFailure
parseOutputArg :: String -> Opt parseOutputArg :: String -> Opt
parseOutputArg str = case List.elemIndex ':' str of parseOutputArg str = case List.elemIndex ':' str of
Just i -> let (lang, _:dir) = splitAt i str in OutputOpt lang (Map.lookup lang generatorFns) dir Just i -> let (lang, _:dir) = splitAt i str in OutputOpt lang (Map.lookup lang generatorFns) dir
Nothing -> OutputOpt str (Map.lookup str generatorFns) "." Nothing -> OutputOpt str (Map.lookup str generatorFns) "."
handleFile :: [(GeneratorFn, FilePath)] -> Bool -> FilePath -> IO () data ImportState = ImportInProgress | ImportFailed | ImportSucceeded FileDesc
handleFile outputs isVerbose filename = do type ImportStateMap = Map.Map String ImportState
text <- readFile filename data CompilerState = CompilerState Bool ImportStateMap
case parseAndCompileFile filename text of type CompilerMonad a = StateT CompilerState IO a
importFile :: Bool -> FilePath -> CompilerMonad (Either FileDesc String)
importFile isVerbose filename = do
fileState <- state (\s@(CompilerState f m) -> case Map.lookup filename m of
d@Nothing -> (d, CompilerState f (Map.insert filename ImportInProgress m))
d -> (d, s))
case fileState of
Just ImportFailed -> return $ Right "File contained errors."
Just ImportInProgress -> return $ Right "File cyclically imports itself."
Just (ImportSucceeded d) -> return $ Left d
Nothing -> do
result <- readAndParseFile isVerbose filename
modify (\(CompilerState f m) -> case result of
Left desc -> CompilerState f (Map.insert filename (ImportSucceeded desc) m)
Right _ -> CompilerState True (Map.insert filename ImportFailed m))
return result
readAndParseFile isVerbose filename = do
textOrError <- liftIO $ catch (fmap Left $ readFile filename)
(\ex -> return $ Right $ show (ex :: IOException))
case textOrError of
Right err -> return $ Right err
Left text -> parseFile isVerbose filename text
parseFile isVerbose filename text = do
let importCallback name = do
let path = tail $ combine ('/':filename) name
importFile isVerbose path
status <- parseAndCompileFile filename text importCallback
case status of
Active desc [] -> do Active desc [] -> do
when isVerbose (print desc) when isVerbose (liftIO $ print desc)
return $ Left desc
let write dir (name, content) = do
let outFilename = dir ++ "/" ++ name
createDirectoryIfMissing True $ takeDirectory outFilename
LZ.writeFile outFilename content
let generate (generatorFn, dir) = do
files <- generatorFn desc
mapM_ (write dir) files
mapM_ generate outputs
Active _ e -> do Active _ e -> do
mapM_ printError (List.sortBy compareErrors e) liftIO $ mapM_ printError (List.sortBy compareErrors e)
exitFailure return $ Right "File contained errors."
Failed e -> do Failed e -> do
mapM_ printError (List.sortBy compareErrors e) liftIO $ mapM_ printError (List.sortBy compareErrors e)
exitFailure return $ Right "File contained errors."
handleFile :: [(GeneratorFn, FilePath)] -> Bool -> FilePath -> CompilerMonad ()
handleFile outputs isVerbose filename = do
result <- importFile isVerbose filename
case result of
Right _ -> return ()
Left desc -> do
let write dir (name, content) = do
let outFilename = dir ++ "/" ++ name
createDirectoryIfMissing True $ takeDirectory outFilename
LZ.writeFile outFilename content
generate (generatorFn, dir) = do
files <- generatorFn desc
mapM_ (write dir) files
liftIO $ mapM_ generate outputs
compareErrors a b = compare (errorPos a) (errorPos b) compareErrors a b = compare (errorPos a) (errorPos b)
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment