summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMatthew Hall <hallmatthew314@gmail.com>2023-02-22 22:23:35 +1300
committerMatthew Hall <hallmatthew314@gmail.com>2023-02-22 22:24:29 +1300
commitbad32a12573bf14968746ea9ad0f6c4f20b50cf1 (patch)
tree26ce098f30f054b2f2a742d2c06b857951ea68db
parent0bde837174fcb9c17cb3adbf6bc3c7407cab10df (diff)
Re-work program structure, MAIN entrypoint + only PROC definitions
-rw-r--r--DSL.hs2
-rw-r--r--DSL/Interpretation.hs11
-rw-r--r--DSL/Parsing.hs14
-rw-r--r--DSL/Types.hs2
-rw-r--r--README.md98
-rw-r--r--examples/fizzbuzz.dumb27
6 files changed, 82 insertions, 72 deletions
diff --git a/DSL.hs b/DSL.hs
index 23f8f4d..54efb28 100644
--- a/DSL.hs
+++ b/DSL.hs
@@ -1,6 +1,6 @@
module DSL where
-import DSL.BaseParsers (parse)
+import DSL.BaseParsers (parse) -- for testing
import DSL.Parsing
import DSL.Interpretation
diff --git a/DSL/Interpretation.hs b/DSL/Interpretation.hs
index 37165c3..d9c53bd 100644
--- a/DSL/Interpretation.hs
+++ b/DSL/Interpretation.hs
@@ -8,6 +8,9 @@ import DSL.Util
import DSL.Intrinsics
import DSL.StdLib (stdlib)
+entrypoint :: ProcName
+entrypoint = "MAIN"
+
newMachine :: Machine
newMachine = Machine { ok=True, stack=[], pTable=M.empty }
@@ -93,8 +96,10 @@ evalBlocks (BLinear b:bs) m = applyLinear m b >>= evalBlocks bs
evalBlocks (BIf c t f:bs) m = applyIf c t f m >>= evalBlocks bs
evalBlocks (BWhile c b:bs) m = applyWhile c b m >>= evalBlocks bs
-interpret :: (ProcTable, Program) -> IO ()
-interpret (t, p) = case mergeProcTables stdlib t of
- Just t' -> () <$ evalBlocks p newMachine{ pTable=t' }
+interpret :: ProcTable -> IO ()
+interpret t = case mergeProcTables stdlib t of
Nothing -> putStrLn "Failed to include stdlib, duplicate proc definition?"
+ Just t' -> case M.lookup entrypoint t' of
+ Nothing -> putStrLn "No MAIN proc defined, aborting."
+ Just b -> () <$ evalBlocks b newMachine{ pTable=t' }
diff --git a/DSL/Parsing.hs b/DSL/Parsing.hs
index 72d6b23..d4d1253 100644
--- a/DSL/Parsing.hs
+++ b/DSL/Parsing.hs
@@ -191,16 +191,8 @@ blockP = firstOf [ whileP
, linearP
]
-programP :: DSLParser ([ProcSpec], Program)
-programP = phrase $ procs `plus` code
+stringToProgram :: String -> Maybe ProcTable
+stringToProgram = (>>=buildProcTable . snd) . parse (tokenizer `chain` program)
where
- procs = mult procP
- code = mult1 blockP
-
-stringToProgram :: String -> Maybe (ProcTable, Program)
-stringToProgram = (>>=(f . snd)) . parse (tokenizer `chain` programP)
- where
- f (ps, b) = case buildProcTable ps of
- Nothing -> Nothing
- Just t -> Just (t, b)
+ program = phrase $ mult procP
diff --git a/DSL/Types.hs b/DSL/Types.hs
index 7467bfd..aa1fb22 100644
--- a/DSL/Types.hs
+++ b/DSL/Types.hs
@@ -69,8 +69,6 @@ type ProcSpec = (ProcName, [Block])
type ProcTable = Map ProcName [Block]
-type Program = [Block]
-
data Machine = Machine { ok :: Bool
, stack :: Stack
, pTable :: ProcTable
diff --git a/README.md b/README.md
index 261168a..e47e1b7 100644
--- a/README.md
+++ b/README.md
@@ -13,14 +13,15 @@ God help you if you want to use this for anything.
### Procedures
-Custom procedures can be created before the main body of the program:
+Code is separated into procedures. A program must define a procedure named `MAIN` to serve as the entrypoint.
```
PROC is-even? 2 OVER % 0 == END
-4 is-even? . '''true'''
-5 is-even? . '''false'''
-PROC illegal "this is an error" . END ''' not allowed, defined after body program body '''
+PROC MAIN
+ 4 is-even? . '''true'''
+ 5 is-even? . '''false'''
+END
```
### Postfix/Reverse Polish notation
@@ -28,24 +29,25 @@ PROC illegal "this is an error" . END ''' not allowed, defined after body progra
Procedures are invoked by pushing its arguments to the stack in reverse order and then calling the procedure:
```
-''' compute 2+1 and print the result (3) '''
-1 2 + .
-
-''' compute 2-1 and print the result (1) '''
-1 2 - .
-
-''' compute 1-2 and print the result (-1) '''
-2 1 - .
-
-''' test if 5 is greater than 6 and print the result (false) '''
-6 5 > .
-
-''' compute 2+3, test if 3 is less than the sum, and print the result '''
-3 2 + 3 < .
-
-''' concatenate two strings and print the result '''
-" but backwards" "it's like LISP" ++ .
-
+PROC
+ ''' compute 2+1 and print the result (3) '''
+ 1 2 + .
+
+ ''' compute 2-1 and print the result (1) '''
+ 1 2 - .
+
+ ''' compute 1-2 and print the result (-1) '''
+ 2 1 - .
+
+ ''' test if 5 is greater than 6 and print the result (false) '''
+ 6 5 > .
+
+ ''' compute 2+3, test if 3 is less than the sum, and print the result '''
+ 3 2 + 3 < .
+
+ ''' concatenate two strings and print the result '''
+ " but backwards" "it's like LISP" ++ .
+END
```
### Comments
@@ -53,14 +55,16 @@ Procedures are invoked by pushing its arguments to the stack in reverse order an
Comments are multi-line only and are opened and closed with three single-quotes:
```
-IF 2 9 % 0 == DO
- ''' TODO: come up with a better message to print
- maybe something to do with the mod result being 0? '''
- "true branch"
-ELSE
- ''' i feel like we could mention that the number is odd? or something? '''
- "false branch"
-END .
+PROC MAIN
+ IF 2 9 % 0 == DO
+ ''' TODO: come up with a better message to print
+ maybe something to do with the mod result being 0? '''
+ "true branch"
+ ELSE
+ ''' i feel like we could mention that the number is odd? or something? '''
+ "false branch"
+ END .
+END
```
### Control-flow
@@ -68,14 +72,16 @@ END .
DSL currently has IF/ELIF/ELSE blocks and WHILE loops:
```
-IF get-some-number 0 == DO
- "the number is zero" .
-ELIF get-some-number 1 == DO
- "the number is one" .
-ELIF get-some-number 2 == DO
- "the number is two" .
-ELSE
- "this number has yet to be discovered by science" .
+PROC MAIN
+ IF get-some-number 0 == DO
+ "the number is zero" .
+ ELIF get-some-number 1 == DO
+ "the number is one" .
+ ELIF get-some-number 2 == DO
+ "the number is two" .
+ ELSE
+ "this number has yet to be discovered by science" .
+ END
END
```
@@ -83,15 +89,23 @@ END
Most characters typically thought-of as 'special' have no special syntactic meaning in DSL. Some exceptions include:
+* Sequences of characters that would be parsed as data literals
* Double-quotes, which start and end string literals
* Three single-quotes in a row, which start and end comment blocks
* Other special character sequences already reserved as intrinsic / proc names
```
-''' this is okay '''
-PROC $(*^$%*&#$%# "this is a string that was just printed" . END
-
-''' this isn't '''
+''' these are okay '''
+PROC foo "this proc has a valid name" . END
+PROC +foo- "this proc has a valid name" . END
+PROC +fo8o- "this proc has a valid name" . END
+PROC $(*^$%*&#$%#]} "this proc has a valid name" . END
+
+''' these aren't '''
+PROC true "this is a parser error" . END
+PROC 123 "this is a parser error" . END
+PROC "foo" "this is a parser error" . END
PROC "foo "this is a parser error" . END
+PROC '''foo''' "this is a parser error" . END
```
diff --git a/examples/fizzbuzz.dumb b/examples/fizzbuzz.dumb
index 2ba6033..f9aa648 100644
--- a/examples/fizzbuzz.dumb
+++ b/examples/fizzbuzz.dumb
@@ -1,14 +1,15 @@
-''' bottom of the stack is the incrementing value, starts at 1 '''
-1
-''' while the incrementing value is <= 100 '''
-WHILE 100 OVER <= DO
- ''' push string "Buzz" if inc. is divisible by 5, else an empty string '''
- 5 OVER % IF 0 == DO "Buzz" ELSE "" END
- ''' push string "Fizz" if inc. is divisible by 3, else an empty string '''
- OVER 3 SWAP % IF 0 == DO "Fizz" ELSE "" END
- ''' concat the two strings and copy the inc., if the string is empty, swap them '''
- ++ OVER SWAP IF DUP "" == DO SWAP END
- ''' print the top of the stack, drop the next item, add 1 to inc. '''
- . DROP 1 +
+PROC MAIN
+ ''' bottom of the stack is the incrementing value, starts at 1 '''
+ 1
+ ''' while the incrementing value is <= 100 '''
+ WHILE 100 OVER <= DO
+ ''' push string "Buzz" if inc. is divisible by 5, else an empty string '''
+ 5 OVER % IF 0 == DO "Buzz" ELSE "" END
+ ''' push string "Fizz" if inc. is divisible by 3, else an empty string '''
+ OVER 3 SWAP % IF 0 == DO "Fizz" ELSE "" END
+ ''' concat the two strings and copy the inc., if the string is empty, swap them '''
+ ++ OVER SWAP IF DUP "" == DO SWAP END
+ ''' print the top of the stack, drop the next item, add 1 to inc. '''
+ . DROP 1 +
+ END
END
-