Skip to content

Commit

Permalink
string support
Browse files Browse the repository at this point in the history
  • Loading branch information
devyn committed Aug 9, 2023
1 parent 76301a7 commit 9058e83
Show file tree
Hide file tree
Showing 6 changed files with 250 additions and 50 deletions.
5 changes: 3 additions & 2 deletions stage1/init.s
Original file line number Diff line number Diff line change
Expand Up @@ -58,8 +58,8 @@ start:
# loop through tokens and print them
call get_token
# make sure token is valid
beqz a0, .Lstart_parse_done
beqz a2, .Lstart_parse_done
beqz a0, .Lstart_token_error
beqz a2, .Lstart_token_error
# save the remaining buffer
mv s3, a0
mv s4, a1
Expand All @@ -71,6 +71,7 @@ start:
# some kind of error
li t0, PARSER_STATUS_OVERFLOW
beq a0, t0, .Lstart_token_overflow
.Lstart_token_error:
la a0, ERR_MSG
ld a1, (ERR_MSG_LENGTH)
call put_buf
Expand Down
36 changes: 18 additions & 18 deletions stage1/memory.s
Original file line number Diff line number Diff line change
Expand Up @@ -240,66 +240,66 @@ acquire_object:
1:
ret

# decrement refcount and deallocate if <= 0
# decrement refcount and drop if <= 0
.global release_object
release_object:
beqz a0, 1f
lw t0, LISP_OBJECT_REFCOUNT(a0)
addi t0, t0, -1
sw t0, LISP_OBJECT_REFCOUNT(a0)
bgtz t0, 1f
j deallocate_object
j drop_object
1:
mv a0, zero
ret

# calls deallocate for an object as well as any of the memory it owns
.global deallocate_object
deallocate_object:
.global drop_object
drop_object:
addi sp, sp, -24
sd ra, 0(sp)
sd s1, 8(sp) # s1 = saved object address
sd s2, 16(sp) # s2 = object type
mv s1, a0
lwu s2, LISP_OBJECT_TYPE(s1)
beqz s2, .Ldeallocate_object_zero # most likely double free
.Ldeallocate_object_cons:
beqz s2, .Ldrop_object_zero # most likely double free
.Ldrop_object_cons:
# check for CONS
li t0, LISP_OBJECT_TYPE_CONS
bne s2, t0, .Ldeallocate_object_string
bne s2, t0, .Ldrop_object_string
# release head
ld a0, LISP_CONS_HEAD(s1)
call release_object
# release tail
ld a0, LISP_CONS_TAIL(s1)
call release_object
j .Ldeallocate_object_end
.Ldeallocate_object_string:
j .Ldrop_object_end
.Ldrop_object_string:
# check for STRING
li t0, LISP_OBJECT_TYPE_STRING
bne s2, t0, .Ldeallocate_object_procedure
bne s2, t0, .Ldrop_object_procedure
# release the buffer x capacity
ld a0, LISP_STRING_BUF(s1)
ld a1, LISP_STRING_CAP(s1)
call deallocate
j .Ldeallocate_object_end
.Ldeallocate_object_procedure:
j .Ldrop_object_end
.Ldrop_object_procedure:
# check for PROCEDURE
li t0, LISP_OBJECT_TYPE_PROCEDURE
bne s2, t0, .Ldeallocate_object_end
bne s2, t0, .Ldrop_object_end
# release data
ld a0, LISP_PROCEDURE_DATA(s1)
call release_object
j .Ldeallocate_object_end
.Ldeallocate_object_symbol:
j .Ldrop_object_end
.Ldrop_object_symbol:
# check for SYMBOL
li t0, LISP_OBJECT_TYPE_SYMBOL
bne s2, t0, .Ldeallocate_object_end
bne s2, t0, .Ldrop_object_end
# symbols should never be released
mv a0, s1
call acquire_object
j 1f
.Ldeallocate_object_zero:
.Ldrop_object_zero:
# print z address and return without deallocating
li a0, 'z'
call putc
Expand All @@ -309,7 +309,7 @@ deallocate_object:
li a0, '\n'
call putc
j 1f
.Ldeallocate_object_end:
.Ldrop_object_end:
mv a0, s1
li a1, LISP_OBJECT_SIZE
call deallocate
Expand Down
42 changes: 42 additions & 0 deletions stage1/object.s
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,16 @@ box_integer:
li a0, LISP_OBJECT_TYPE_INTEGER
j make_obj

# make string from buf (a0), len (a1)
# object takes ownership of the buf and will deallocate it on drop
.global box_string
box_string:
mv a3, zero
mv a2, a1
mv a1, a0
li a0, LISP_OBJECT_TYPE_STRING
j make_obj

# Return only head from cons in a0
# Takes ownership of reference, so make sure to acquire first if you don't want to lose the cons
# Returns nil if not cons
Expand Down Expand Up @@ -245,6 +255,8 @@ print_obj:
beq t0, t1, .Lprint_obj_integer
li t1, LISP_OBJECT_TYPE_SYMBOL
beq t0, t1, .Lprint_obj_symbol
li t1, LISP_OBJECT_TYPE_STRING
beq t0, t1, .Lprint_obj_string
li t1, LISP_OBJECT_TYPE_PROCEDURE
beq t0, t1, .Lprint_obj_procedure
# print <??> if unrecognized
Expand Down Expand Up @@ -294,6 +306,36 @@ print_obj:
ld a1, LISP_SYMBOL_LEN(s1)
call put_buf
j .Lprint_obj_ret
.Lprint_obj_string:
# get string buf, len
addi sp, sp, -0x10
sd s2, 0x00(sp)
sd s3, 0x08(sp)
ld s2, LISP_STRING_BUF(s1)
ld s3, LISP_STRING_LEN(s1)
# put quote
li a0, 0x22
call putc
# loop through chars, print double quote if quote
1:
beqz s3, 2f
lb a0, (s2)
call putc
lb a0, (s2)
li t0, 0x22
addi s2, s2, 1
addi s3, s3, -1
bne a0, t0, 1b # not a quote
call putc # print extra quote
j 1b
2:
# closing quote
li a0, 0x22
call putc
ld s2, 0x00(sp)
ld s3, 0x08(sp)
addi sp, sp, 0x10
j .Lprint_obj_ret
.Lprint_obj_procedure:
# print <address data>
li a0, '<'
Expand Down
54 changes: 53 additions & 1 deletion stage1/parser.s
Original file line number Diff line number Diff line change
Expand Up @@ -409,7 +409,59 @@ parse_token:
sd t1, PARSER_STATE_E_FLAG(s2) # set assoc
j .Lparse_token_ret_ok
.Lparse_token_string:
j .Lparse_token_error # WIP
# determine true length of the string
li t1, 2
bltu s5, t1, .Lparse_token_error # string must have at least two chars: ""
addi t0, s4, 1 # current addr (skip first ")
addi t1, s5, -1 # remaining length counter (skip first ")
li t2, 0 # actual length
li t4, 0x22 # 0x22 = "
.Lparse_token_string_length_loop:
beqz t1, .Lparse_token_error # shouldn't run out of token
lb t3, (t0)
addi t0, t0, 1
addi t1, t1, -1
addi t2, t2, 1
bne t3, t4, .Lparse_token_string_length_loop # not a quote
# check if the quote is followed by a quote (escape)
beqz t1, .Lparse_token_string_length_end # end of string
lb t3, (t0)
# error condition: token contains non-escaped quote in non-terminal position
bne t3, t4, .Lparse_token_error
# skip the second quote
addi t0, t0, 1
addi t1, t1, -1
j .Lparse_token_string_length_loop
.Lparse_token_string_length_end:
# allocate string buffer, keep length in s7 for now
addi s7, t2, -1 # the last quote is always over-counted, remove it
mv a0, s7
li a1, 1 # byte alignment
call allocate
beqz a0, .Lparse_token_error # alloc failed
# turn the buffer into an object
mv a1, s7
call box_string
beqz a0, .Lparse_token_error # alloc failed
# save the object into s6
mv s6, a0
# set up the loop to copy the string contents, handling escapes
addi t0, s4, 1 # current src addr (skip first ")
ld t1, LISP_STRING_BUF(s6) # current dest addr
ld t2, LISP_STRING_LEN(s6) # remaining length counter
li t4, 0x22 # 0x22 = "
.Lparse_token_string_copy_loop:
beqz t2, .Lparse_token_place_object # end of string
lb t3, (t0)
sb t3, (t1)
addi t0, t0, 1
addi t1, t1, 1
addi t2, t2, -1
# skip a char from the src if this is a quote
# we already validated that every quote inside the string is doubled
bne t3, t4, .Lparse_token_string_copy_loop # not a quote
addi t0, t0, 1
j .Lparse_token_string_copy_loop
.Lparse_token_address:
j .Lparse_token_error # WIP
.Lparse_token_place_object:
Expand Down
24 changes: 24 additions & 0 deletions stage1/words.s
Original file line number Diff line number Diff line change
Expand Up @@ -116,12 +116,30 @@ INITIAL_WORDS:
.ascii "car"
.balign 8

.quad car
.2byte 4
.byte LISP_OBJECT_TYPE_INTEGER
.ascii "car$"
.balign 8

.quad proc_cdr
.2byte 3
.byte LISP_OBJECT_TYPE_PROCEDURE
.ascii "cdr"
.balign 8

.quad cdr
.2byte 4
.byte LISP_OBJECT_TYPE_INTEGER
.ascii "cdr$"
.balign 8

.quad uncons
.2byte 7
.byte LISP_OBJECT_TYPE_INTEGER
.ascii "uncons$"
.balign 8

.quad proc_proc
.2byte 4
.byte LISP_OBJECT_TYPE_PROCEDURE
Expand All @@ -134,6 +152,12 @@ INITIAL_WORDS:
.ascii "eval"
.balign 8

.quad eval
.2byte 5
.byte LISP_OBJECT_TYPE_INTEGER
.ascii "eval$"
.balign 8

.quad allocate
.2byte 9
.byte LISP_OBJECT_TYPE_INTEGER
Expand Down
Loading

0 comments on commit 9058e83

Please sign in to comment.