Skip to content

Commit

Permalink
Implement display funtions and tests
Browse files Browse the repository at this point in the history
  • Loading branch information
Willyboar committed May 28, 2023
1 parent bd71551 commit 5b58a8f
Show file tree
Hide file tree
Showing 2 changed files with 151 additions and 16 deletions.
48 changes: 38 additions & 10 deletions src/glove.gleam
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,6 @@ pub type Inst {
}

/// Display function for Instructions
/// UNFINISHED
pub fn display_inst(inst: Inst) -> String {
case inst {
Add(a, b) -> "add " <> display_value(a) <> ", " <> display_value(b)
Expand Down Expand Up @@ -115,8 +114,8 @@ pub fn display_inst(inst: Inst) -> String {
Copy(val) -> "copy " <> display_value(val)
Ret(val) -> {
case val {
Some(val) -> "ret " <> display_value(val)
None -> "ret"
Some(val) -> "ret " <> display_value(val) <> "\n"
None -> "ret\n"
}
}
Jnz(val, if_nonzero, if_zero) ->
Expand Down Expand Up @@ -239,7 +238,7 @@ pub fn new_datadef() -> DataDef {
pub fn display_data_def(def: DataDef) -> String {
let linkage_str = display_linkage(def.linkage)
let align_str = case def.align {
Some(align) -> "align " <> int.to_string(align)
Some(align) -> " align " <> int.to_string(align)
None -> ""
}

Expand All @@ -252,7 +251,7 @@ pub fn display_data_def(def: DataDef) -> String {
})
|> string.join(", ")

linkage_str <> "data $" <> def.name <> " = " <> align_str <> " { " <> items_str <> " }"
linkage_str <> "data $" <> def.name <> " =" <> align_str <> " { " <> items_str <> " }"
}

/// QBE aggregate type definition
Expand Down Expand Up @@ -337,7 +336,7 @@ pub fn display_block(block: Block) -> String {
|> list.map(display_statement)
|> string.join("\n")

label <> ":\n" <> statements
label <> "\n" <> statements
}

/// Adds a new instruction to the block
Expand All @@ -360,15 +359,44 @@ pub type Function {
Function(
linkage: Linkage,
name: String,
arguments: #(Type, Value),
return_ty: Type,
arguments: List(#(Type, Value)),
return_ty: Option(Type),
blocks: List(Block),
)
}

/// Display function for functions
pub fn display_function() -> String {
todo
pub fn display_function(func: Function) -> String {
let linkage_str = display_linkage(func.linkage)
let name_str = func.name
let return_str = case func.return_ty {
Some(ty) -> display_type(ty)
None -> ""
}
let args_str = display_arguments(func.arguments)
let blocks_str = display_blocks(func.blocks)

linkage_str <> "function" <> " " <> return_str <> " " <> "$" <> name_str <> "(" <> args_str <> ")" <> " {\n" <> blocks_str <> "}"
}

pub fn display_arguments(arguments: List(#(Type, Value))) -> String {
case arguments {
[] -> ""
_ ->
arguments
|> list.index_map(fn(_, arg) {
case arg {
#(ty, val) -> display_type(ty) <> " " <> display_value(val)
}
})
|> string.join(", ")
}
}

pub fn display_blocks(blocks: List(Block)) -> String {
blocks
|> list.map(fn(block) { display_block(block) })
|> string.join("\n")
}

/// Instantiates an empty function and returns it
Expand Down
119 changes: 113 additions & 6 deletions test/glove_test.gleam
Original file line number Diff line number Diff line change
Expand Up @@ -76,12 +76,12 @@ pub fn display_statement_test() {
let volatile = glove.Volatile(glove.Ret(Some(glove.Const(0))))
volatile
|> glove.display_statement
|> should.equal("ret 0")
|> should.equal("ret 0\n")

let empty_volatile = glove.Volatile(glove.Ret(None))
empty_volatile
|> glove.display_statement
|> should.equal("ret")
|> should.equal("ret\n")
}

// Tests for QBE.Block Display
Expand All @@ -90,7 +90,7 @@ pub fn display_block_test() {
let empty_block = glove.Block("label", [])
empty_block
|> glove.display_block()
|> should.equal("label:\n")
|> should.equal("label\n")

// Test block with statements
let statements = [
Expand All @@ -105,7 +105,7 @@ pub fn display_block_test() {
let block_with_statements = glove.Block("label", statements)
block_with_statements
|> glove.display_block
|> should.equal("label:\n%temp1 =w add %a, %b\nret %temp1")
|> should.equal("label\n%temp1 =w add %a, %b\nret %temp1\n")
}

// Tests for QBE.Linkage Display
Expand Down Expand Up @@ -315,13 +315,13 @@ pub fn display_inst_test() {
let ret1 = glove.Ret(Some(glove.Const(10)))
ret1
|> glove.display_inst
|> should.equal("ret 10")
|> should.equal("ret 10\n")

// Test case for returning without a value
let ret2 = glove.Ret(None)
ret2
|> glove.display_inst
|> should.equal("ret")
|> should.equal("ret\n")

// Test case for conditional jump if nonzero
let jnz = glove.Jnz(glove.Const(1), "label1", "label2")
Expand Down Expand Up @@ -420,3 +420,110 @@ pub fn display_data_def_test() {
let result = glove.display_data_def(def)
should.equal(result, expected)
}

// Tests for Linkage functions
pub fn private_test() {
let expected = glove.Linkage(exported: False, section: None, secflags: None)
let result = glove.private()
should.equal(result, expected)
}

pub fn private_with_section_test() {
let section = "mysection"
let expected =
glove.Linkage(exported: False, section: Some(section), secflags: None)
let result = glove.private_with_section(section)
should.equal(result, expected)
}

pub fn public_test() {
let expected = glove.Linkage(exported: True, section: None, secflags: None)
let result = glove.public()
should.equal(result, expected)
}

pub fn public_with_section_test() {
let section = "mysection"
let expected =
glove.Linkage(exported: True, section: Some(section), secflags: None)
let result = glove.public_with_section(section)
should.equal(result, expected)
}

pub fn display_data_test() {
let data_def =
glove.DataDef(
linkage: glove.Linkage(exported: True, section: None, secflags: None),
name: "str",
align: None,
items: [
#(glove.Byte, glove.Str("hello world")),
#(glove.Byte, glove.Constant(0)),
],
)

let expected = "export data $str = { b \"hello world\", b 0 }"
let result = glove.display_data_def(data_def)
should.equal(result, expected)
}

pub fn display_function_test() {
let function =
glove.Function(
linkage: glove.Linkage(exported: True, section: None, secflags: None),
name: "main",
arguments: [],
return_ty: Some(glove.Word),
blocks: [
glove.Block(
"@start",
[
glove.Volatile(glove.Call(
glove.Global("puts"),
[#(glove.Long, glove.Global("str"))],
)),
glove.Volatile(glove.Ret(Some(glove.Const(0)))),
],
),
],
)

let expected =
"export function w $main() {\n@start\ncall $puts(l $str)\nret 0\n}"

let result = glove.display_function(function)
should.equal(result, expected)
}

pub fn display_blocks_test() {
let blocks = [
glove.Block(
"@start",
[
glove.Volatile(glove.Call(
glove.Global("puts"),
[#(glove.Long, glove.Global("str"))],
)),
glove.Volatile(glove.Ret(Some(glove.Const(0)))),
],
),
]

let expected = "@start\ncall $puts(l $str)\nret 0\n"

let result = glove.display_blocks(blocks)
should.equal(result, expected)
}

pub fn display_arguments_test() {
let arguments = [
#(glove.Word, glove.Global("arg1")),
#(glove.Byte, glove.Global("arg2")),
#(glove.Long, glove.Global("arg3")),
]

let expected = "w $arg1, b $arg2, l $arg3"

let result = glove.display_arguments(arguments)
should.equal(result, expected)
}

0 comments on commit 5b58a8f

Please sign in to comment.