view modules/ast.tp @ 251:2557ce4e671f

Fix a couple of compiler bugs. topenv was getting initialized in multiple places. This resulted in multiple copies of modules getting created which caused problems for macro expansion. Additionally, arguments were not being marked as declared during code generation so assigning to an argument that was not closed over generated invalid C code.
author Michael Pavone <pavone@retrodev.com>
date Fri, 11 Apr 2014 22:29:32 -0700
parents b76f683d076e
children 004946743678
line wrap: on
line source

{
	_binary     <- 0
	_string     <- 1
	_int        <- 2
	_symbol     <- 3
	_call       <- 4
	_object     <- 5
	_sequence   <- 6
	_assignment <- 7
	_lambda     <- 8

	#{
		binary <- { _binary }
		stringlit <- { _string }
		intlit <- { _int }
		sym <- { _symbol }
		call <- { _call }
		obj <- { _object }
		sequence <- { _sequence }
		assignment <- { _assignment }
		lambda <- { _lambda }

		binaryOp:withArgs <- :opname :_left _right {
			#{
				nodeType <- { _binary }
				left <- _left
				op <- opname
				right <- _right

				leftAssociative? <- {
					op != "|"
				}
				stringIndent <- :indent {
					(left stringIndent: indent) . " " . op . (right stringIndent: indent)
				}
				string <- {
					stringIndent: ""
				}
			}
		}

		stringLit <- :_val {
			#{
				nodeType <- { _string }
				val <- _val
				stringIndent <- :indent {
					"\"" . val . "\""
				}
				string <- {
					stringIndent: ""
				}
			}
		}

		intLit:withBits:andBase:signed? <- :_val :_bits :_base :_signed? {
			#{
				nodeType <- { _int }
				val <- _val
				base <- _base
				bits <- _bits
				signed? <- _signed?
				stringIndent <- :indent {
					suffix <- ""
					if: bits != 32 || (not: signed?) {
						suffix <- (if: signed? {"i"} else: {"u"}) . bits
					}
					if: base = 16 {
						"0x" . (hex: val) . suffix
					} else: {
						if: base = 2 {
							str <- "0b"
							i <- bits - 1
							printzero <- false
							while: { i >= 0 } do: {
								str <- str . (if: (lshift: 1 by: i) and val > 0 {
									printzero <- true
									"1"
								} else: {
									if: printzero {"0"} else: {""}
								})
								i <- i - 1
							}
							str . suffix
						} else: {
							(string: val) . suffix
						}
					}
				}
				string <- {
					stringIndent: ""
				}
			}
		}

		symbol <- :_name {
			#{
				nodeType <- { _symbol }
				name <- _name
				stringIndent <- :indent {
					name
				}
				string <- {
					stringIndent: ""
				}
			}
		}

		funcall:withArgs:hasReceiver? <- :_tocall :_args :_receiver? {
			#{
				tocall <- _tocall
				args <- _args
				hasReceiver? <- _receiver?
				stringIndent <- :indent {
					argparts <- []
					if: (tocall nodeType) = _symbol {
						argparts <- (tocall name) splitOn: ":"
					} else: {
						argparts <- [tocall stringIndent: indent]
					}
					curarg <- args
					str <- ""
					if: hasReceiver? {
						str <- ((curarg value) stringIndent: indent) . " "
						curarg <- curarg tail
					}
					foreach: argparts :idx part {
						str <- str . part . ":"
						if: (not: (curarg empty?)) {
							str <- str . " " . ((curarg value) stringIndent: indent)
							curarg <- curarg tail
						}
					}
					while: { not: (curarg empty?) } do: {
						str <- str . " " . ((curarg value) stringIndent: indent)
						curarg <- curarg tail
					}
					str
				}
				string <- {
					stringIndent: ""
				}
			}
		}

		object <- :_messages {
			#{
				nodeType <- { _object }
				messages <- _messages
				stringIndent <- :indent {
					nextindent <- "\t" . indent
					(messages fold: "#{" with: :acc el {
						acc . "\n" . nextindent . (el stringIndent: nextindent)
					}) . "\n" . indent . "}"
				}
				string <- {
					stringIndent: ""
				}
			}
		}

		seqLit:array? <- :_els :_array? {
			#{
				nodeType <- { _sequence }
				els <- _els
				array? <- _array?
				stringIndent <- :indent {
					nextIndent <- "\t" . indent
					(els fold: (if: array? {"#["} else: {"["}) with: :acc el {
						acc . "\n" . nextIndent . (el stringIndent: nextIndent)
					}) . "\n" . indent . "]"
				}
				string <- {
					stringIndent: ""
				}
			}
		}

		assign:to <- :_expr :_sym {
			#{
				nodeType <- { _assignment }
				assign <- _expr
				to <- _sym
				stringIndent <- :indent {
					(to stringIndent: indent) . " <- " . (assign stringIndent: indent)
				}
				string <- {
					stringIndent: ""
				}
			}
		}

		lambda:withArgs <- :_exprs :_args {
			#{
				nodeType <- { _lambda }
				args <- _args
				expressions <- _exprs
				stringIndent <- :indent {
					argStr <- args join: " "
					if: (argStr length) > 0 {
						argStr <- argStr . " "
					}
					nextIndent <- "\t" . indent
					(expressions fold: argStr . "{" with: :acc el {
						acc . "\n" . nextIndent . (el stringIndent: nextIndent)
					}) . "\n" . indent . "}"
				}
				string <- {
					stringIndent: ""
				}
			}
		}
	}
}