From 0827870285cd7f67e51774e14a88b4b777acd8eb Mon Sep 17 00:00:00 2001 From: Billy Moore Date: Fri, 23 Jan 2026 19:29:01 +0000 Subject: [PATCH 1/2] Rewrite the parsing for Expressions to a) not check types and b) parse left -> right. --- src/HSPC/Parse.hs | 229 +++++++++++++++++++++------------------------- 1 file changed, 102 insertions(+), 127 deletions(-) diff --git a/src/HSPC/Parse.hs b/src/HSPC/Parse.hs index c3fc1a7..18f05e9 100644 --- a/src/HSPC/Parse.hs +++ b/src/HSPC/Parse.hs @@ -10,7 +10,6 @@ module HSPC.Parse where import Data.Int (Int64) -import Data.Map qualified as Map import HSPC.Tokenize (HSPCToken (..)) data Program = Program String [Block] @@ -83,10 +82,10 @@ parse _ = Left MustStartWithProgramStatement parseMainProgramBlock :: [HSPCToken] -> Either ParseError Block parseMainProgramBlock (VarKeyWordTok : tocs) = do (vars, rest) <- parseVariableDeclarations [] tocs - (res, _) <- parseStatements (Map.fromList vars) [] rest + (res, _) <- parseStatements [] rest return $ MainProgramBlock vars res parseMainProgramBlock (BeginKeyWordTok : tocs) = do - (res, _) <- parseStatements Map.empty [] tocs + (res, _) <- parseStatements [] tocs return $ MainProgramBlock [] res parseMainProgramBlock _ = Left InvalidStartOfBlock @@ -109,17 +108,6 @@ parseVariableDeclaration (IdentifierTok name : ColonTok : dataTypeToc : xs) = do return ((name, datatype), rest) parseVariableDeclaration toks = Left $ ExpectedVariableDeclaration toks -breakLastOuter :: (HSPCToken -> Bool) -> [HSPCToken] -> ([HSPCToken], [HSPCToken]) -breakLastOuter breakCond toks = go (reverse toks) [] 0 - where - go :: [HSPCToken] -> [HSPCToken] -> Int -> ([HSPCToken], [HSPCToken]) - go [] _ _ = (toks, []) - go (CloseBracketTok : rest) acc i = go rest (CloseBracketTok : acc) (i + 1) - go (OpenBracketTok : rest) acc i = go rest (OpenBracketTok : acc) (i - 1) - go (lastTok : rest) acc 0 - | breakCond lastTok = (reverse rest, lastTok : acc) - go (lastTok : rest) acc i = go rest (lastTok : acc) i - splitToMatchingBracket :: [HSPCToken] -> Either ParseError ([HSPCToken], [HSPCToken]) splitToMatchingBracket toks = go toks [] 0 where @@ -132,160 +120,147 @@ splitToMatchingBracket toks = go toks [] 0 go (x : xs) acc i = go xs (x : acc) i go [] _ _ = Left UnmatchedBracket -parseStatements :: Map.Map String HSPCDataType -> [Statement] -> [HSPCToken] -> Either ParseError ([Statement], [HSPCToken]) -parseStatements _ acc (EndKeyWordTok : xs) = Right (reverse acc, xs) -parseStatements _ _ [] = Left ExpectedEndStatement -parseStatements vars acc xs = do - (expr, restWithSemiColon) <- parseStatement vars xs +parseStatements :: [Statement] -> [HSPCToken] -> Either ParseError ([Statement], [HSPCToken]) +parseStatements acc (EndKeyWordTok : xs) = Right (reverse acc, xs) +parseStatements _ [] = Left ExpectedEndStatement +parseStatements acc xs = do + (expr, restWithSemiColon) <- parseStatement xs rest <- removeLeadingSemiColon restWithSemiColon - parseStatements vars (expr : acc) rest + parseStatements (expr : acc) rest -parseStatement :: Map.Map String HSPCDataType -> [HSPCToken] -> Either ParseError (Statement, [HSPCToken]) -parseStatement varMap (IdentifierTok name : AssignmentTok : xs) = do +parseStatement :: [HSPCToken] -> Either ParseError (Statement, [HSPCToken]) +parseStatement (IdentifierTok name : AssignmentTok : xs) = do let (rhs, rest) = break (`elem` [SemiColonTok, ElseKeyWordTok]) xs - op <- case Map.lookup name varMap of - Just dt -> parseOperand dt rhs - Nothing -> Left $ VariableNotDeclared name + op <- parseExpression rhs return (Assignment name op, rest) parseStatement - _ (HaltBuiltInTok : OpenBracketTok : CloseBracketTok : xs) = Right (Halt (IntLiteral 0), xs) parseStatement - _ (HaltBuiltInTok : OpenBracketTok : xs) = do (internal, rest) <- splitToMatchingBracket xs - op <- parseOperand IntegerType internal + op <- parseExpression internal return (Halt op, rest) -- "IF cond THEN statement (; | ELSE elseStatement;)" -- ELSE IF is simply an if statement where elseSatement -- is another if statement. -parseStatement varMap (IfKeyWordTok : xs) = do +parseStatement (IfKeyWordTok : xs) = do (cond, afterThen) <- parseIfCondition xs - (statement, afterStatement) <- parseStatement varMap afterThen + (statement, afterStatement) <- parseStatement afterThen case afterStatement of (SemiColonTok : outsideOfStatement) -> return (If cond statement NOP, SemiColonTok : outsideOfStatement) (ElseKeyWordTok : afterElse) -> do - (elseStatement, afterElseStatement) <- parseStatement varMap afterElse + (elseStatement, afterElseStatement) <- parseStatement afterElse outsideOfStatement <- removeLeadingSemiColon afterElseStatement return (If cond statement elseStatement, SemiColonTok : outsideOfStatement) _ -> Left $ ExpectedToken SemiColonTok where parseIfCondition :: [HSPCToken] -> Either ParseError (Expression, [HSPCToken]) parseIfCondition = parseCondition ThenKeyWordTok -parseStatement varMap (WhileKeyWordTok : xs) = do +parseStatement (WhileKeyWordTok : xs) = do (cond, afterThen) <- parseWhileCondition xs - (statement, afterStatement) <- parseStatement varMap afterThen + (statement, afterStatement) <- parseStatement afterThen outsideOfStatement <- removeLeadingSemiColon afterStatement return (While cond statement, SemiColonTok : outsideOfStatement) where parseWhileCondition :: [HSPCToken] -> Either ParseError (Expression, [HSPCToken]) parseWhileCondition = parseCondition DoKeyWordTok -parseStatement _ tok = Left $ NotImplemented "parseStatement" tok +parseStatement tok = Left $ NotImplemented "parseStatement" tok parseCondition :: HSPCToken -> [HSPCToken] -> Either ParseError (Expression, [HSPCToken]) parseCondition doneTok tokens = do let (condTokens, afterCond) = break (== doneTok) tokens - cond <- parseOperand BooleanType condTokens + cond <- parseExpression condTokens return (cond, drop 1 afterCond) -parseOperand :: HSPCDataType -> [HSPCToken] -> Either ParseError Expression -parseOperand IntegerType = parseIntOperand -parseOperand BooleanType = parseBoolOperand - --- IntOperand = Term { ("+" | "-") Term } --- Term = Factor { ("*" | "div") Factor } --- Factor = ("+" | "-") Factor | Number | "(" IntOperand ")" --- Number = // an integer -parseIntOperand :: [HSPCToken] -> Either ParseError Expression -parseIntOperand tokens = case breakLastOuter (`elem` [PlusTok, MinusTok]) tokens of - -- starts with +- - ([], after) -> parseTerm after - -- doesn't contain +- - (before, []) -> parseTerm before - (_, [PlusTok]) -> Left $ ExpectedOperand "Expected operand after +" - (before, PlusTok : after) -> do - left <- parseIntOperand before - right <- parseTerm after - return $ Add left right - (_, [MinusTok]) -> Left $ ExpectedOperand "Expected operand after -" - (before, MinusTok : after) -> do - left <- parseIntOperand before - right <- parseTerm after - return $ Subtract left right - _ -> error "Should be unreachable since we break on PlusTok || MinusTok" +-- BoolTerm = BoolFactor { "and" BoolFactor } +-- BoolFactor = "not" BoolFactor | Relation +-- Relation = SimpleExpr [ RelOp SimpleExpr ] +-- SimpleExpr = Term { AddOp Term } +-- Term = Factor { MulOp Factor } +-- Factor = + Factor | - Factor | Integer | True | False | "(" Expression ")" +-- RelOp = "==" | "!=" | "<" | ">" | "<=" | ">=" +-- AddOp = "+" | "-" +-- MulOp = "*" | "/" +parseExpression :: [HSPCToken] -> Either ParseError Expression +parseExpression exprTokens = do + (result, remaining) <- parseExpressionInternal exprTokens + case remaining of + [] -> Right result + (tok : _) -> Left $ UnexpectedToken tok where - parseTerm :: [HSPCToken] -> Either ParseError Expression - parseTerm toks = case breakLastOuter (`elem` [IntDivideTok, MultiplyTok]) toks of - (before, []) -> parseFactor before - (_, [IntDivideTok]) -> Left $ ExpectedOperand "Expected operand after 'div'" - (before, IntDivideTok : after) -> do - left <- parseIntOperand before - right <- parseFactor after - return $ IntDivide left right - (_, [MultiplyTok]) -> Left $ ExpectedOperand "Expected operand after *" - (before, MultiplyTok : after) -> do - left <- parseIntOperand before - right <- parseFactor after - return $ Multiply left right - _ -> error "Should be unreachable since we break on IntDivideTok || MultiplyTok" + parseExpressionInternal :: [HSPCToken] -> Either ParseError (Expression, [HSPCToken]) + parseExpressionInternal toks = do + (left, rest) <- parseBoolTerm toks + loopOr left rest + where + loopOr acc (OrTok : xs) = do + (right, rest') <- parseBoolTerm xs + loopOr (BoolOr acc right) rest' + loopOr acc tokens = Right (acc, tokens) + + parseBoolTerm :: [HSPCToken] -> Either ParseError (Expression, [HSPCToken]) + parseBoolTerm toks = do + (left, rest) <- parseBoolFactor toks + loopAnd left rest + where + loopAnd acc (AndTok : xs) = do + (right, rest') <- parseBoolFactor xs + loopAnd (BoolAnd acc right) rest' + loopAnd acc tokens = Right (acc, tokens) + + parseBoolFactor :: [HSPCToken] -> Either ParseError (Expression, [HSPCToken]) + parseBoolFactor (NotTok : xs) = do + (inner, rest) <- parseBoolFactor xs + return (BoolNot inner, rest) + parseBoolFactor toks = parseRelation toks + + -- TODO: parse relations such as ==, >=, < + parseRelation :: [HSPCToken] -> Either ParseError (Expression, [HSPCToken]) + parseRelation = parseSimpleExpr + + parseSimpleExpr :: [HSPCToken] -> Either ParseError (Expression, [HSPCToken]) + parseSimpleExpr toks = do + (left, rest) <- parseTerm toks + loopAdd left rest + where + loopAdd acc (PlusTok : xs) = do + (right, rest') <- parseTerm xs + loopAdd (Add acc right) rest' + loopAdd acc (MinusTok : xs) = do + (right, rest') <- parseTerm xs + loopAdd (Subtract acc right) rest' + loopAdd acc tokens = Right (acc, tokens) + + parseTerm :: [HSPCToken] -> Either ParseError (Expression, [HSPCToken]) + parseTerm toks = do + (left, rest) <- parseFactor toks + loopMul left rest + where + loopMul acc (MultiplyTok : xs) = do + (right, rest') <- parseFactor xs + loopMul (Multiply acc right) rest' + loopMul acc (IntDivideTok : xs) = do + (right, rest') <- parseFactor xs + loopMul (IntDivide acc right) rest' + loopMul acc tokens = Right (acc, tokens) - parseFactor :: [HSPCToken] -> Either ParseError Expression - parseFactor [LiteralIntTok n] = Right $ IntLiteral n - -- TODO: check that this variable exists - parseFactor [IdentifierTok name] = Right $ Identifier name + parseFactor :: [HSPCToken] -> Either ParseError (Expression, [HSPCToken]) parseFactor (PlusTok : xs) = do - operand <- parseFactor xs - return $ UnaryPlus operand + (inner, rest) <- parseFactor xs + return (UnaryPlus inner, rest) parseFactor (MinusTok : xs) = do - operand <- parseFactor xs - return $ UnaryMinus operand + (inner, rest) <- parseFactor xs + return (UnaryMinus inner, rest) + parseFactor (LiteralIntTok n : xs) = Right (IntLiteral n, xs) + parseFactor (LiteralBoolTok b : xs) = Right (BoolLiteral b, xs) + parseFactor (IdentifierTok name : xs) = Right (Identifier name, xs) parseFactor (OpenBracketTok : xs) = do - (inside, remaining) <- splitToMatchingBracket xs - case remaining of - [] -> parseIntOperand inside + (expr, rest) <- parseExpressionInternal xs + case rest of + (CloseBracketTok : final) -> Right (expr, final) + [] -> Left $ ExpectedOperand "Expected closing bracket ')'" (tok : _) -> Left $ UnexpectedToken tok - parseFactor (tok : _) = Left $ UnexpectedToken tok parseFactor [] = Left $ ExpectedOperand "Expected operand" - --- BoolOperand = BoolTerm { or BoolTerm } --- BoolTerm = BoolFactor { and BoolFactor } --- BoolFactor = not BoolFactor | BoolPrimary --- BoolPrimary = True | False | ( BoolOperand ) -parseBoolOperand :: [HSPCToken] -> Either ParseError Expression -parseBoolOperand tokens = case breakLastOuter (== OrTok) tokens of - (before, []) -> parseBoolTerm before - (_, [OrTok]) -> Left $ ExpectedOperand "Expected operand after 'div'" - (before, OrTok : after) -> do - left <- parseBoolTerm before - right <- parseBoolTerm after - return $ BoolOr left right - _ -> error "Should be unreachable since we break on OrTok" - where - parseBoolTerm :: [HSPCToken] -> Either ParseError Expression - parseBoolTerm toks = case breakLastOuter (== AndTok) toks of - (before, []) -> parseBoolFactor before - (_, [AndTok]) -> Left $ ExpectedOperand "Expected operand after 'div'" - (before, AndTok : after) -> do - left <- parseBoolFactor before - right <- parseBoolFactor after - return $ BoolAnd left right - _ -> error "Should be unreachable since we break on AndTok" - - parseBoolFactor :: [HSPCToken] -> Either ParseError Expression - parseBoolFactor (NotTok : op) = do - opAsExpr <- parseBoolFactor op - return $ BoolNot opAsExpr - parseBoolFactor toks = parseBoolPrimary toks - - parseBoolPrimary :: [HSPCToken] -> Either ParseError Expression - parseBoolPrimary [LiteralBoolTok bool] = Right $ BoolLiteral bool - parseBoolPrimary [IdentifierTok name] = Right $ Identifier name - parseBoolPrimary (OpenBracketTok : xs) = do - (inside, remaining) <- splitToMatchingBracket xs - case remaining of - [] -> parseBoolOperand inside - (tok : _) -> Left $ UnexpectedToken tok - parseBoolPrimary (tok : _) = Left $ UnexpectedToken tok - parseBoolPrimary [] = Left $ ExpectedOperand "Expected boolean operand" + parseFactor (tok : _) = Left $ UnexpectedToken tok From aeff125d912588cce297ba850f4d303cb7e9f332 Mon Sep 17 00:00:00 2001 From: Billy Moore Date: Wed, 28 Jan 2026 13:01:53 +0000 Subject: [PATCH 2/2] Implement comparisons between ints and associated testing. --- README.md | 2 +- src/HSPC/CodeGen.hs | 16 ++++++++++ src/HSPC/Parse.hs | 26 +++++++++++++++-- src/HSPC/Tokenize.hs | 19 ++++++++++++ test/Main.hs | 7 ++++- .../comparison_equality.golden | 0 test/sample_programs/comparison_equality.pas | 29 +++++++++++++++++++ .../comparison_greater_than.golden | 0 .../comparison_greater_than.pas | 17 +++++++++++ .../comparison_less_than.golden | 0 test/sample_programs/comparison_less_than.pas | 29 +++++++++++++++++++ test/sample_programs/while_less_than.golden | 0 test/sample_programs/while_less_than.pas | 14 +++++++++ .../sample_programs/while_not_equal_10.golden | 0 test/sample_programs/while_not_equal_10.pas | 12 ++++++++ 15 files changed, 167 insertions(+), 4 deletions(-) create mode 100644 test/sample_programs/comparison_equality.golden create mode 100644 test/sample_programs/comparison_equality.pas create mode 100644 test/sample_programs/comparison_greater_than.golden create mode 100644 test/sample_programs/comparison_greater_than.pas create mode 100644 test/sample_programs/comparison_less_than.golden create mode 100644 test/sample_programs/comparison_less_than.pas create mode 100644 test/sample_programs/while_less_than.golden create mode 100644 test/sample_programs/while_less_than.pas create mode 100644 test/sample_programs/while_not_equal_10.golden create mode 100644 test/sample_programs/while_not_equal_10.pas diff --git a/README.md b/README.md index 9de7c6e..3a47e6d 100644 --- a/README.md +++ b/README.md @@ -18,7 +18,7 @@ Increments: - [X] Booleans - [X] Branching (if statements) - [X] While Loops -- [ ] Comparisons +- [X] Comparisons - [ ] Blocks as statements - [ ] Strings (WriteLn("Hello World")) - [ ] For Loops diff --git a/src/HSPC/CodeGen.hs b/src/HSPC/CodeGen.hs index 57e1abd..316a5ce 100644 --- a/src/HSPC/CodeGen.hs +++ b/src/HSPC/CodeGen.hs @@ -95,6 +95,16 @@ generateStatement offsetMap (Assignment name op) = Nothing -> error $ "Variable " ++ name ++ " doesn't exist." generateStatement _ ast = error $ "CodeGen for " ++ show ast ++ " not implemented" +generateComparison :: OffsetMap -> Expression -> Expression -> Word8 -> [Word8] +generateComparison offsetMap op1 op2 condByte = + generateExpression offsetMap op2 + ++ [0x50] -- push rax + ++ generateExpression offsetMap op1 + ++ [0x48, 0x3b, 0x04, 0x24] -- cmp rax, [rsp] (op1 vs op2) + ++ [0x0f, condByte, 0xc0] -- set{cond} al + ++ [0x48, 0x0f, 0xb6, 0xc0] -- movzx rax, al + ++ [0x48, 0x83, 0xc4, 0x08] -- add rsp, 8 (release stack space) + generateExpression :: OffsetMap -> Expression -> [Word8] generateExpression _ (IntLiteral i) = [0x48, 0xb8] ++ int64ToLE i -- movabs rax i generateExpression _ (BoolLiteral b) = @@ -116,6 +126,12 @@ generateExpression offsetMap (Multiply op1 op2) = ++ generateExpression offsetMap op2 ++ [0x48, 0x0f, 0xaf, 0x04, 0x24] -- imul rax [rsp] ++ [0x48, 0x83, 0xc4, 0x08] -- add rsp 8 (release stack space) +generateExpression offsetMap (Equal op1 op2) = generateComparison offsetMap op1 op2 0x94 +generateExpression offsetMap (NotEqual op1 op2) = generateComparison offsetMap op1 op2 0x95 +generateExpression offsetMap (GreaterThan op1 op2) = generateComparison offsetMap op1 op2 0x9f +generateExpression offsetMap (GreaterOrEqualThan op1 op2) = generateComparison offsetMap op1 op2 0x9d +generateExpression offsetMap (LessThan op1 op2) = generateComparison offsetMap op1 op2 0x9c +generateExpression offsetMap (LessOrEqualThan op1 op2) = generateComparison offsetMap op1 op2 0x9e generateExpression offsetMap (UnaryPlus op) = generateExpression offsetMap op -- unary + is a nop generateExpression offsetMap (UnaryMinus op) = generateExpression offsetMap op diff --git a/src/HSPC/Parse.hs b/src/HSPC/Parse.hs index 18f05e9..e4f55ac 100644 --- a/src/HSPC/Parse.hs +++ b/src/HSPC/Parse.hs @@ -48,6 +48,12 @@ data Expression | IntDivide Expression Expression | UnaryPlus Expression | UnaryMinus Expression + | Equal Expression Expression + | NotEqual Expression Expression + | GreaterThan Expression Expression + | GreaterOrEqualThan Expression Expression + | LessThan Expression Expression + | LessOrEqualThan Expression Expression deriving (Show, Eq) data ParseError @@ -216,9 +222,25 @@ parseExpression exprTokens = do return (BoolNot inner, rest) parseBoolFactor toks = parseRelation toks - -- TODO: parse relations such as ==, >=, < parseRelation :: [HSPCToken] -> Either ParseError (Expression, [HSPCToken]) - parseRelation = parseSimpleExpr + parseRelation toks = do + parseSimpleExpr toks >>= handleOperatorAndRight + where + handleOperatorAndRight (left, op : xs) + | Just constructor <- matchOpTokenToOperator op = do + (right, rest) <- parseSimpleExpr xs + Right (constructor left right, rest) + -- no comparison operator + handleOperatorAndRight (left, rest) = Right (left, rest) + + matchOpTokenToOperator :: HSPCToken -> Maybe (Expression -> Expression -> Expression) + matchOpTokenToOperator EqualTok = Just Equal + matchOpTokenToOperator NotEqualTok = Just NotEqual + matchOpTokenToOperator GreaterThanTok = Just GreaterThan + matchOpTokenToOperator GreaterThanEqualTok = Just GreaterOrEqualThan + matchOpTokenToOperator LessThanTok = Just LessThan + matchOpTokenToOperator LessThanEqualTok = Just LessOrEqualThan + matchOpTokenToOperator _ = Nothing parseSimpleExpr :: [HSPCToken] -> Either ParseError (Expression, [HSPCToken]) parseSimpleExpr toks = do diff --git a/src/HSPC/Tokenize.hs b/src/HSPC/Tokenize.hs index 3b3dd04..92b9fc2 100644 --- a/src/HSPC/Tokenize.hs +++ b/src/HSPC/Tokenize.hs @@ -25,6 +25,12 @@ data HSPCToken | ColonTok | SemiColonTok | IntDivideTok + | NotEqualTok + | EqualTok + | GreaterThanEqualTok + | GreaterThanTok + | LessThanTok + | LessThanEqualTok | OrTok | AndTok | NotTok @@ -35,6 +41,13 @@ data HSPCToken | IdentifierTok String deriving (Show, Eq) +-- tokenizeOperator ('!' : '=' : xs) = AssignmentTok : tokenize xs +-- tokenizeOperator ('=' : '=' : xs) = AssignmentTok : tokenize xs +-- tokenizeOperator ('>' : '=' : xs) = AssignmentTok : tokenize xs +-- tokenizeOperator ('<' : '=' : xs) = AssignmentTok : tokenize xs +-- tokenizeOperator ('<' : xs) = AssignmentTok : tokenize xs +-- tokenizeOperator ('<' : xs) = AssignmentTok : tokenize xs + tokenize :: String -> [HSPCToken] tokenize [] = [] tokenize ('{' : cs) = tokenize $ dropWhile (/= '}') cs @@ -73,6 +86,12 @@ tokenizeIdentifierOrKeyWord s = IdentifierTok s tokenizeOperator :: String -> [HSPCToken] tokenizeOperator (':' : '=' : xs) = AssignmentTok : tokenize xs +tokenizeOperator ('<' : '>' : xs) = NotEqualTok : tokenize xs +tokenizeOperator ('>' : '=' : xs) = GreaterThanEqualTok : tokenize xs +tokenizeOperator ('<' : '=' : xs) = LessThanEqualTok : tokenize xs +tokenizeOperator ('=' : xs) = EqualTok : tokenize xs +tokenizeOperator ('>' : xs) = GreaterThanTok : tokenize xs +tokenizeOperator ('<' : xs) = LessThanTok : tokenize xs tokenizeOperator (':' : xs) = ColonTok : tokenize xs tokenizeOperator (';' : xs) = SemiColonTok : tokenize xs tokenizeOperator ('(' : xs) = OpenBracketTok : tokenize xs diff --git a/test/Main.hs b/test/Main.hs index 91db9be..18cdc24 100644 --- a/test/Main.hs +++ b/test/Main.hs @@ -44,7 +44,12 @@ testSuite = TestSpec "IF ELSE" "if_else" 40, TestSpec "IF ELSE IF" "if_else_if" 40, TestSpec "IF with complex cond" "if_complex_cond" 40, - TestSpec "WHILE basic example" "while" 0 + TestSpec "WHILE basic example" "while" 0, + TestSpec "WHILE not equal (<> 10)" "while_not_equal_10" 10, + TestSpec "WHILE less than (< 1000)" "while_less_than" 100, + TestSpec "Greater than (> and >=)" "comparison_greater_than" 40, + TestSpec "Less than (< and <=)" "comparison_less_than" 23, + TestSpec "Equality (= and <>)" "comparison_equality" 22 ] main :: IO () diff --git a/test/sample_programs/comparison_equality.golden b/test/sample_programs/comparison_equality.golden new file mode 100644 index 0000000..e69de29 diff --git a/test/sample_programs/comparison_equality.pas b/test/sample_programs/comparison_equality.pas new file mode 100644 index 0000000..9beb9c3 --- /dev/null +++ b/test/sample_programs/comparison_equality.pas @@ -0,0 +1,29 @@ +program EQExample; + +var + i: integer; +begin + i := 10; + + // False + if (i <> 10) then + i := 30; + + // True + if (i = 10) then + i := i + 10; // i := 20 + + // False + if (i = 18) then + i := i + 5 + // True + else if (i = 20) then + i := i + 2; // i := 22 + + // False + if (i <> 22) then + i := i + 1; + + + halt(i); // should be 22 +end. diff --git a/test/sample_programs/comparison_greater_than.golden b/test/sample_programs/comparison_greater_than.golden new file mode 100644 index 0000000..e69de29 diff --git a/test/sample_programs/comparison_greater_than.pas b/test/sample_programs/comparison_greater_than.pas new file mode 100644 index 0000000..b38e2c5 --- /dev/null +++ b/test/sample_programs/comparison_greater_than.pas @@ -0,0 +1,17 @@ +program GTExample; + +var + i: integer; + j: integer; +begin + i := 10; + j := 12; + + if (i > 8) then + i := 30; + + if (j >= 12) then + j := 10; + + halt(i+j); // should be 40 +end. diff --git a/test/sample_programs/comparison_less_than.golden b/test/sample_programs/comparison_less_than.golden new file mode 100644 index 0000000..e69de29 diff --git a/test/sample_programs/comparison_less_than.pas b/test/sample_programs/comparison_less_than.pas new file mode 100644 index 0000000..6c9a7de --- /dev/null +++ b/test/sample_programs/comparison_less_than.pas @@ -0,0 +1,29 @@ +program LTExample; + +var + i: integer; +begin + i := 10; + + // False + if (i < 8) then + i := 30; + + // True + if (i < 100) then + i := i + 10; // i := 20 + + // False + if (i <= 18) then + i := i + 5 + // True + else if (i <= 21) then + i := i + 2; // i := 22 + + // True + if (i <= 22) then + i := i + 1; // i := 23 + + + halt(i); // should be 23 +end. diff --git a/test/sample_programs/while_less_than.golden b/test/sample_programs/while_less_than.golden new file mode 100644 index 0000000..e69de29 diff --git a/test/sample_programs/while_less_than.pas b/test/sample_programs/while_less_than.pas new file mode 100644 index 0000000..9515e68 --- /dev/null +++ b/test/sample_programs/while_less_than.pas @@ -0,0 +1,14 @@ +program WhileExample; + +var + i : integer; +begin + i := 0; + + while i < 1000 do + i := i + 1; + + i := i div 10; // i := 100 + + halt(i); +end. diff --git a/test/sample_programs/while_not_equal_10.golden b/test/sample_programs/while_not_equal_10.golden new file mode 100644 index 0000000..e69de29 diff --git a/test/sample_programs/while_not_equal_10.pas b/test/sample_programs/while_not_equal_10.pas new file mode 100644 index 0000000..243ff7f --- /dev/null +++ b/test/sample_programs/while_not_equal_10.pas @@ -0,0 +1,12 @@ +program WhileExample; + +var + i : integer; +begin + i := 0; + + while i <> 10 do + i := i + 1; + + halt(i); +end.