111 lines
3.1 KiB
Nim
111 lines
3.1 KiB
Nim
#[
|
|
|
|
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 <http://www.gnu.org/licenses/>.
|
|
|
|
|
|
]#
|
|
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.")
|
|
|