From b5001499d7990114eec947e7fed41a484f4320d0 Mon Sep 17 00:00:00 2001 From: vvsob Date: Thu, 25 Dec 2025 18:41:04 +0300 Subject: [PATCH] interpreter first version --- app/Main.hs | 10 ++++---- crafting-interpreters-hs.cabal | 2 +- src/Lox/Interpreter.hs | 44 ++++++++++++++++++++++++++++++++++ src/Lox/Scanner.hs | 13 +++++++++- 4 files changed, 63 insertions(+), 6 deletions(-) create mode 100644 src/Lox/Interpreter.hs diff --git a/app/Main.hs b/app/Main.hs index 2289177..6966ae6 100644 --- a/app/Main.hs +++ b/app/Main.hs @@ -1,10 +1,12 @@ -module Main where - import Lox.Scanner +import Lox.Parser +import Lox.Interpreter run :: String -> IO () -run source = mapM_ print tokens - where tokens = scanTokensFromSource source +run source = print result + where result = eval expr + expr = parse tokens + tokens = scanTokensFromSource source main :: IO () main = getLine >>= run diff --git a/crafting-interpreters-hs.cabal b/crafting-interpreters-hs.cabal index c515836..260e578 100644 --- a/crafting-interpreters-hs.cabal +++ b/crafting-interpreters-hs.cabal @@ -54,7 +54,7 @@ common warnings ghc-options: -Wall library - exposed-modules: Lox.Scanner, Lox.Expr, Lox.Parser + exposed-modules: Lox.Scanner, Lox.Expr, Lox.Parser, Lox.Interpreter build-depends: base ^>=4.18.3.0, mtl, extra hs-source-dirs: src default-language: Haskell2010 diff --git a/src/Lox/Interpreter.hs b/src/Lox/Interpreter.hs new file mode 100644 index 0000000..32ab64e --- /dev/null +++ b/src/Lox/Interpreter.hs @@ -0,0 +1,44 @@ +module Lox.Interpreter ( + eval +) where + +import Lox.Expr +import Lox.Scanner +import Control.Monad.State + +data InterpreterState = InterpreterState + +eval :: Expr -> Object +eval expr = evalState (interpret expr) InterpreterState + +interpret :: Expr -> State InterpreterState Object +interpret (Literal value) = return value +interpret (Grouping expr) = interpret expr +interpret (Unary op expr) = do + right <- interpret expr + case (getType op, right) of + (MINUS, NumberObject x) -> return $ NumberObject (-x) + (BANG, NullObject) -> return $ BoolObject False + (BANG, BoolObject x) -> return $ BoolObject (not x) + (BANG, _) -> return $ BoolObject True + _ -> error "Type error" +interpret (Binary leftExpr op rightExpr) = do + left <- interpret leftExpr + right <- interpret rightExpr + case (getType op, left, right) of + (PLUS, NumberObject x, NumberObject y) -> return $ NumberObject (x + y) + (MINUS, NumberObject x, NumberObject y) -> return $ NumberObject (x - y) + (SLASH, NumberObject x, NumberObject y) -> return $ NumberObject (x / y) + (STAR, NumberObject x, NumberObject y) -> return $ NumberObject (x * y) + + (GREATER, NumberObject x, NumberObject y) -> return $ BoolObject (x > y) + (GREATER_EQUAL, NumberObject x, NumberObject y) -> return $ BoolObject (x >= y) + (LESS, NumberObject x, NumberObject y) -> return $ BoolObject (x < y) + (LESS_EQUAL, NumberObject x, NumberObject y) -> return $ BoolObject (x <= y) + + (PLUS, StringObject s, StringObject t) -> return $ StringObject (s ++ t) + + (EQUAL_EQUAL, x, y) -> return $ BoolObject (x == y) + + _ -> error "Type error" + diff --git a/src/Lox/Scanner.hs b/src/Lox/Scanner.hs index cd4e7df..48446be 100644 --- a/src/Lox/Scanner.hs +++ b/src/Lox/Scanner.hs @@ -22,7 +22,18 @@ data TokenType = LEFT_PAREN | RIGHT_PAREN | LEFT_BRACE | RIGHT_BRACE | EOF deriving (Show, Eq) -data Object = NullObject | StringObject String | NumberObject Double | BoolObject Bool deriving Show +data Object = NullObject + | StringObject String + | NumberObject Double + | BoolObject Bool + deriving (Eq) + +instance Show Object where + show NullObject = "Nil" + show (StringObject s) = show s + show (NumberObject x) = show x + show (BoolObject False) = "false" + show (BoolObject True) = "true" data Token = Token { getType :: TokenType,