diff --git a/implementations/Nim/defs.nim b/implementations/Nim/defs.nim deleted file mode 100644 index 49c6b4b..0000000 --- a/implementations/Nim/defs.nim +++ /dev/null @@ -1,45 +0,0 @@ -#[ - - Copyright © 2021 Simon Forman - - This file is part of Bliss - - Bliss is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - Bliss is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with Bliss. If not see . - - -]# -import streams, strutils, fp, reader, types - -proc add_def(def: string, dictionary: var JoyMapType) = - let d = read_str(def) - let sym = d.head - case sym.kind: - of joyAtom: - dictionary = dictionary + (sym.atomVal, d.tail) - else: - raise newException(ValueError, def) - -proc defs_file2dict(defs_filename: string = "defs.txt"): JoyMapType = - var strm = newFileStream(defs_filename, fmRead) - var dictionary = newMap[string, JoyListType]() - var line = "" - if not isNil(strm): - while strm.readLine(line): - if line.isEmptyOrWhitespace: - continue - add_def(line, dictionary) - strm.close() - return dictionary - -var dictionary* = defs_file2dict() diff --git a/implementations/Nim/joy.nim b/implementations/Nim/joy.nim deleted file mode 100644 index d74cb7b..0000000 --- a/implementations/Nim/joy.nim +++ /dev/null @@ -1,145 +0,0 @@ -#[ - - Copyright © 2021 Simon Forman - - This file is part of Bliss - - Bliss is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - Bliss is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with Bliss. If not see . - - -]# -import rdstdin, bigints, fp, printer, reader, types, joylib, utils, defs - - -# Handle Ctrl-C by raising an IOError to break out of the mainloop -# without waiting for the user to press enter. -proc ctrlc() {.noconv.} = - raise newException(IOError, "Got Ctrl-C, bye!") - -setControlCHook(ctrlc) - - -proc joy_eval(sym: string, state: var JoyState): JoyState = - case sym - - # Integer Math - - of "+": push_int(pop_int(state) + pop_int(state), state) - of "*": push_int(pop_int(state) * pop_int(state), state) - of "-": - let tos = pop_int(state) - push_int(pop_int(state) - tos, state) - of "/": - let tos = pop_int(state) - push_int(pop_int(state) div tos, state) - of "%": - let tos = pop_int(state) - push_int(pop_int(state) mod tos, state) - - # Comparision - - of "<": - let tos = pop_int(state) - let second = pop_int(state) - push_bool(second < tos, state) - of ">": - let tos = pop_int(state) - let second = pop_int(state) - push_bool(second > tos, state) - of "<=": - let tos = pop_int(state) - let second = pop_int(state) - push_bool(second <= tos, state) - of ">=": - let tos = pop_int(state) - let second = pop_int(state) - push_bool(second >= tos, state) - of "=": - let tos = pop_int(state) - let second = pop_int(state) - push_bool(second == tos, state) - of "<>": - let tos = pop_int(state) - let second = pop_int(state) - push_bool(second != tos, state) - - # Boolean logic - - of "and": # Have to pop, Nim `and` short-circuits. - let tos = pop_bool(state) - let second = pop_bool(state) - push_bool(tos and second, state) - of "or": # Have to pop, Nim `or` short-circuits. - let tos = pop_bool(state) - let second = pop_bool(state) - push_bool(tos or second, state) - - # Built-in Functions and Combinators - - of "bool": truthy(state) - of "branch": branch(state) - of "clear": clear(state) - of "concat": concat(state) - of "cons": cons(state) - of "dip": dip(state) - of "dup": dup(state) - of "first": first(state) - of "i": i(state) - of "loop": loop(state) - of "pop": pop(state) - of "rest": rest(state) - of "stack": stack(state) - of "swaack": swaack(state) - of "swap": swap(state) - - else: - let def = dictionary.get(sym) - if def.isEmpty: - raise newException(ValueError, "Unknown: " & sym) - state.expression = def.get() ++ state.expression - state - - -proc joy(state: var JoyState) = - while not state.expression.isEmpty: - # echo print_stack(state.stack), " . ", print_expression(state.expression) - let term = state.expression.head - state.expression = state.expression.tail - case term.kind - of joyInt, joyList, joyTrue, joyFalse: - state.stack = term ^^ state.stack - of joyAtom: - state = joy_eval(term.atomVal, state) - of joyParseError: - echo term.errorMessage - break - - - -var state0: JoyState = (stack: Nil[JoyType](), expression: Nil[JoyType]()) -var state: JoyState -while true: - try: - let e = read_str(readLineFromStdin("joy? ")) - state = (stack: state0.stack, expression: e) - except IOError: - break - try: - joy(state) - except: - echo getCurrentExceptionMsg() - echo print_stack(state0.stack) - continue - echo print_stack(state.stack) - state0 = state diff --git a/implementations/Nim/joylib.nim b/implementations/Nim/joylib.nim deleted file mode 100644 index f5b20ac..0000000 --- a/implementations/Nim/joylib.nim +++ /dev/null @@ -1,110 +0,0 @@ -#[ - - Copyright © 2021 Simon Forman - - This file is part of Bliss - - Bliss is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - Bliss is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with Bliss. If not see . - - -]# -import bigints, fp, types, utils - -proc branch*(state: var JoyState) = - let true_body = pop_list(state) - let false_body = pop_list(state) - if pop_bool(state): - state.expression = true_body ++ state.expression - else: - state.expression = false_body ++ state.expression - -proc clear*(state: var JoyState) = - state.stack = Nil[JoyType]() - -proc concat*(state: var JoyState) = - let tos = pop_list(state) - let second = pop_list(state) - push_list((second ++ tos), state) - -proc cons*(state: var JoyState) = - let tos = pop_list(state) - let second = pop_any(state) - push_list((second ^^ tos), state) - -proc dip*(state: var JoyState) = - let body = pop_list(state) - let tos = pop_any(state) - state.expression = body ++ tos ^^ state.expression - -proc dup*(state: var JoyState) = - if state.stack.isEmpty: - raise newException(ValueError, "Cannot dup empty stack.") - state.stack = state.stack.head ^^ state.stack - -proc first*(state: var JoyState) = - let tos = pop_list(state) - if tos.isEmpty: - raise newException(ValueError, "Cannot take first of empty list.") - state.stack = tos.head ^^ state.stack - -proc i*(state: var JoyState) = - let body = pop_list(state) - state.expression = body ++ state.expression - -proc loop*(state: var JoyState) = - let tos = pop_any(state) - case tos.kind: - of joyList: - if pop_bool(state): - state.expression = tos.listVal ++ tos ^^ j_loop ^^ state.expression - else: - raise newException(ValueError, "Loop body not a list.") - -proc pop*(state: var JoyState) = - if state.stack.isEmpty: - raise newException(ValueError, "Cannot pop empty stack.") - state.stack = state.stack.tail - -proc rest*(state: var JoyState) = - let tos = pop_list(state) - if tos.isEmpty: - raise newException(ValueError, "Cannot take rest of empty list.") - push_list(tos.tail, state) - -proc stack*(state: var JoyState) = - push_list(state.stack, state) - -proc swaack*(state: var JoyState) = - let tos = pop_list(state) - let stack = state.stack - state.stack = tos - push_list(stack, state) - -proc swap*(state: var JoyState) = - let tos = pop_any(state) - let second = pop_any(state) - state.stack = second ^^ tos ^^ state.stack - -proc truthy*(state: var JoyState) = - let tos = pop_any(state) - case tos.kind: - of joyTrue, joyFalse: - state.stack = tos ^^ state.stack - of joyInt: - push_bool(tos.intVal != zero, state) - of joyList: - push_bool(not tos.listVal.isEmpty, state) - else: - raise newException(ValueError, "Cannot Boolify.") - diff --git a/implementations/Nim/printer.nim b/implementations/Nim/printer.nim deleted file mode 100644 index 102e616..0000000 --- a/implementations/Nim/printer.nim +++ /dev/null @@ -1,43 +0,0 @@ -#[ - - Copyright © 2021 Simon Forman - - This file is part of Bliss - - Bliss is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - Bliss is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with Bliss. If not see . - - -]# -import strutils, bigints, fp, types - -proc pr_str(thing: JoyType): string - -proc joystr(s: JoyListType): string = - s.map(pr_str).asSeq.join(" ") - -proc pr_str(thing: JoyType): string = - case thing.kind - of joyAtom: thing.atomVal - of joyInt: thing.intVal.toString - of joyList: "[" & joystr(thing.listVal) & "]" - of joyParseError: thing.errorMessage - of joyTrue: "true" - of joyFalse: "false" - -proc print_expression*(stack: JoyListType): string = - joystr(stack) - -proc print_stack*(stack: JoyListType): string = - joystr(stack.reverse) - diff --git a/implementations/Nim/reader.nim b/implementations/Nim/reader.nim deleted file mode 100644 index 5e5cee3..0000000 --- a/implementations/Nim/reader.nim +++ /dev/null @@ -1,107 +0,0 @@ -#[ - - Copyright © 2021 Simon Forman - - This file is part of Bliss - - Bliss is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - Bliss is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with Bliss. If not see . - - -]# -import pegs, bigints, fp, types - -type - - Token = string - - Reader = tuple - tokens : seq[Token] - position: int - eof: bool - -let token_pattern = peg""" - - Token <- Bracket / Symbol - - Bracket <- '[' / ']' - Symbol <- (!Bracket \S)+ - - """ - -# TODO: Maybe use PEG eventParser? - - -proc peek(reader: Reader): Token = - reader.tokens[reader.position] - - -proc next(reader: var Reader): Token = - if reader.eof: - raise newException(ValueError, "EOF") - result = peek(reader) - inc reader.position - reader.eof = reader.position >= reader.tokens.len - - -proc read_atom(reader: var Reader): JoyType = - let tok = next(reader) - if tok =~ peg"^('+' / '-' )? \d+$": - JoyType(kind: joyInt, intVal: tok.initBigInt) - elif tok == "true": j_true - elif tok == "false": j_false - else: JoyType(kind: joyAtom, atomVal: tok) - - -proc read_form(reader: var Reader): JoyType - - -proc read_list(reader: var Reader): JoyType = - var items : seq[JoyType] = @[] - discard next(reader) # Skip the '['. - while true: - if reader.eof: - return JoyType(kind: joyParseError, errorMessage: "EOF while scanning list.") - if peek(reader) == "]": - discard next(reader) # Skip the ']'. - break - items.add(read_form(reader)) - JoyType(kind: joyList, listVal: items.asList) - - -proc read_form(reader: var Reader): JoyType = - if reader.eof: - # Blank or empty input, not really an error. - JoyType(kind: joyParseError, errorMessage: "") - elif peek(reader) == "[": - read_list(reader) - else: - read_atom(reader) - - -proc tokens_to_reader(tokens: seq[Token]): Reader = - var reader: Reader = ( - tokens: tokens, - position: 0, - eof: tokens.len == 0 - ) - reader - - -proc read_str*(str: string): JoyListType = - var items : seq[JoyType] = @[] - var reader = tokens_to_reader(findAll(str, token_pattern)) - while not reader.eof: - items.add(read_form(reader)) - items.asList - diff --git a/implementations/Nim/types.nim b/implementations/Nim/types.nim deleted file mode 100644 index 4e85d73..0000000 --- a/implementations/Nim/types.nim +++ /dev/null @@ -1,58 +0,0 @@ -#[ - - Copyright © 2021 Simon Forman - - This file is part of Bliss - - Bliss is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - Bliss is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with Bliss. If not see . - - -]# -import bigints, fp - -type - - JoyListType* = List[JoyType] - JoyMapType* = Map[string, JoyListType] - - JoyState* = tuple - stack: JoyListType - expression: JoyListType - - JoyTypeType* = enum - joyAtom, - joyFalse, - joyInt, - joyList, - joyParseError, - joyTrue - - JoyType* = ref object - case kind*: JoyTypeType - of joyAtom: atomVal*: string - of joyFalse, joyTrue: nil - of joyInt: intVal*: BigInt - of joyList: listVal*: JoyListType - of joyParseError: errorMessage*: string - - -# Singleton values for Boolean type. - -let j_true* = JoyType(kind: joyTrue) -let j_false* = JoyType(kind: joyFalse) - -# Singleton values for Symbols. - -let j_loop* = JoyType(kind: joyAtom, atomVal: "loop") - diff --git a/implementations/Nim/utils.nim b/implementations/Nim/utils.nim deleted file mode 100644 index 860ee37..0000000 --- a/implementations/Nim/utils.nim +++ /dev/null @@ -1,69 +0,0 @@ -#[ - - Copyright © 2021 Simon Forman - - This file is part of Bliss - - Bliss is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - Bliss is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with Bliss. If not see . - - -]# -import bigints, fp, types - - -proc pop_any*(state: var JoyState): JoyType = - # TODO: detect and report nils. - if state.stack.isEmpty: - raise newException(ValueError, "Not enough values on stack.") - let a = state.stack.head - state.stack = state.stack.tail - return a - -proc pop_bool*(state: var JoyState): bool = - let a = pop_any(state) - case a.kind: - of joyTrue: result = true - of joyFalse: result = false - else: - raise newException(ValueError, "Not a Boolean value.") - -proc pop_int*(state: var JoyState): BigInt = - let a = pop_any(state) - case a.kind: - of joyInt: - return a.intVal - else: - raise newException(ValueError, "Not an integer.") - -proc pop_list*(state: var JoyState): JoyListType = - let a = pop_any(state) - case a.kind: - of joyList: - return a.listVal - else: - raise newException(ValueError, "Not a list.") - - -proc push_int*(a: BigInt, state: var JoyState) = - state.stack = JoyType(kind: joyInt, intVal: a) ^^ state.stack - -proc push_list*(a: JoyListType, state: var JoyState) = - state.stack = JoyType(kind: joyList, listVal: a) ^^ state.stack - -proc push_bool*(a: bool, state: var JoyState) = - if a: - state.stack = j_true ^^ state.stack - else: - state.stack = j_false ^^ state.stack -