JCRS
Join Calculus flavored Rewriting System
Language
<> buffer ?r :
<> $r push ?v , $r _none :
! $r ~value $v ;
;
<> $r get [ ~?cb ] , $r _value ?v :
! $cb $v ;
! $r _none ;
;
! $r _none ;
;
! buffer my-buffer ;
! my-buffer push 5 ;
! my-buffer get [ io print ] ;
! creator name "florian" ;
? creator name ~?name :
! io print $name ;
;
Example Bytecode Textual Representation
unknow length of bytes are
??
(unknown as if I don't want to count them)$x
represents the interning of symbolx
rule ??
pre-conds 1
pre-cond 2
word $buffer
make-var $r
post-conds 3
post-cond
rule ??
pre-conds 2
pre-cond 3
push-var $r
word $push
nake-var $v
pre-cond 2
push-var $r
word $_none
post-conds 1
post-cond
fact 9
push-var $r
word $_value
push-var $v
post-cond
rule ??
pre-conds 2
pre-cond 3
push-var $r
word $get
word $[
make-multi-var $cb
word $]
pre-cond 3
push-var $r
word $_value
make-var $v
post-conds 2
post-cond
fact 6
push-multi-var $cb
push-var $v
post-cond
fact 6
push-var $r
word $_none
post-cond
fact 6
push-var $r
word $_none
Implementation
begin
"""
One memory is a $(2^16) long table of two bytes.
- `data::SVector{2^16, UInt16}`: the table, a UInt16 is named a cell
- `read_pointer::UInt16`: where are we reading in the table
- `write_pointer::UInt16`: where are we writing in the table
"""
@kwdef mutable struct Memory
data::SVector{2^16, UInt16} = @SVector zeros(2^16)
read_pointer::UInt16 = 0
write_pointer::UInt16 = 0
end
"""
The Machine.
- `facts::Memory`: the on-going processes
- `rules::Memory`: the syncing rules
- `bindings::Memory`: the temporay bindings when using `?x` and `\$x` in a application of the post-conditions of a query or a rule
- `program::Memory`: the program loaded, and future bytes to execute
"""
@kwdef mutable struct Machine
facts::Memory # TODO: should act like a linked list to drop facts easily
rules::Memory
bindings::Memory
program::Memory
end
"""
The Operation Codes.
- `name::Symbol`: the name of the code
- `bytecode::UInt16`: the bytes to match against
- `params::UInt8`: the number of params it expects
"""
struct OpCode
name::Symbol
bytecode::UInt16
params::UInt8
description::String
end
opcodes_by_bytecode::Dict{UInt16, OpCode} = Dict()
function make_opcode(n::Symbol, b::UInt16, p::UInt8, d::String)
o = OpCode(n, b, UInt8(p), d)
opcodes_by_bytecode[b] = o
return o
end
MK_RULE = make_opcode(:mk_rule, 0x8000, 0x01, "Make a rule: [number of cells to copy at `Machine.rules`]")
MK_QEST = make_opcode(:mk_qest, 0x8001, 0x01, "Make a query: [number of cells to execute]")
MK_PREC = make_opcode(:mk_prec, 0x8002, 0x01, "Make a pre-condition: [number of symbols in pre-condition to match against for accepting the pre-condition]")
NB_PREC = make_opcode(:nb_prec, 0x8003, 0x01, "Indicate the number of pre-conditions in a rule: [number of pre-conditions]")
MK_POST = make_opcode(:mk_post, 0x8004, 0x00, "Indicate that next is a post-condition")
NB_POST = make_opcode(:nb_post, 0x8005, 0x01, "Indicate the number of post-condition: [number of post-conditions]")
MK_FACT = make_opcode(:mk_fact, 0x8006, 0x01, "Make a fact: [number of cells to copy to `Machine.facts`]")
MK_WORD = make_opcode(:mk_word, 0x8007, 0x01, "Make a word: [word identifier]")
MK_SVAR = make_opcode(:mk_svar, 0x8008, 0x01, "Make a single symbol variable: [variable identifier in `Machine.bindings`]")
LD_SVAR = make_opcode(:ld_svar, 0x8009, 0x01, "Load a single symbol variable: [key to `Machine.bindings`]")
MK_MVAR = make_opcode(:mk_mvar, 0x800a, 0x01, "Make a multiple symbols variable: [variable identifier in `Machine.bindings`]")
LD_MVAR = make_opcode(:ld_mvar, 0x800b, 0x01, "Load a multiple symbols variable: [key to `Machine.bindings`]")
LI_UTF1 = make_opcode(:li_utf1, 0x800c, 0x01, "Make a 1 or 2 byte long char: [UTF-8 bytes]")
LI_UTF2 = make_opcode(:li_utf2, 0x800d, 0x02, "Make a 3 or 4 byte long char: [UTF-8 bytes]")
LI_INTG = make_opcode(:li_intg, 0x800e, 0x01, "Make an integer: [the integer]")
md"""
### Memory
$(@doc Memory)
### Machine
$(@doc Machine)
### Operation Codes
$(@doc OpCode)
"""
end
Memory
One memory is a 65536 long table of two bytes.
data::SVector{2^16, UInt16}
: the table, a UInt16 is named a cellread_pointer::UInt16
: where are we reading in the tablewrite_pointer::UInt16
: where are we writing in the table
Machine
The Machine.
facts::Memory
: the on-going processesrules::Memory
: the syncing rulesbindings::Memory
: the temporay bindings when using?x
and$x
in a application of the post-conditions of a query or a ruleprogram::Memory
: the program loaded, and future bytes to execute
Operation Codes
The Operation Codes.
name::Symbol
: the name of the codebytecode::UInt16
: the bytes to match againstparams::UInt8
: the number of params it expects
MK_RULE
Make a rule: [number of cells to copy at Machine.rules
]
bytecode::UInt16: 0x8000
params::UInt8: 1
MK_QEST
Make a query: [number of cells to execute]
bytecode::UInt16: 0x8001
params::UInt8: 1
MK_PREC
Make a pre-condition: [number of symbols in pre-condition to match against for accepting the pre-condition]
bytecode::UInt16: 0x8002
params::UInt8: 1
NB_PREC
Indicate the number of pre-conditions in a rule: [number of pre-conditions]
bytecode::UInt16: 0x8003
params::UInt8: 1
MK_POST
Indicate that next is a post-condition
bytecode::UInt16: 0x8004
params::UInt8: 0
NB_POST
Indicate the number of post-condition: [number of post-conditions]
bytecode::UInt16: 0x8005
params::UInt8: 1
MK_FACT
Make a fact: [number of cells to copy to Machine.facts
]
bytecode::UInt16: 0x8006
params::UInt8: 1
MK_WORD
Make a word: [word identifier]
bytecode::UInt16: 0x8007
params::UInt8: 1
MK_SVAR
Make a single symbol variable: [variable identifier in Machine.bindings
]
bytecode::UInt16: 0x8008
params::UInt8: 1
LD_SVAR
Load a single symbol variable: [key to Machine.bindings
]
bytecode::UInt16: 0x8009
params::UInt8: 1
MK_MVAR
Make a multiple symbols variable: [variable identifier in Machine.bindings
]
bytecode::UInt16: 0x800a
params::UInt8: 1
LD_MVAR
Load a multiple symbols variable: [key to Machine.bindings
]
bytecode::UInt16: 0x800b
params::UInt8: 1
LI_UTF1
Make a 1 or 2 byte long char: [UTF-8 bytes]
bytecode::UInt16: 0x800c
params::UInt8: 1
LI_UTF2
Make a 3 or 4 byte long char: [UTF-8 bytes]
bytecode::UInt16: 0x800d
params::UInt8: 2
LI_INTG
Make an integer: [the integer]
bytecode::UInt16: 0x800e
params::UInt8: 1