view modules/ast.tp @ 358:27477c8c2823

Add support for simple type annotations in parser and update llhello sample with a possible new low-level dialect syntax leveraging those annotations
author Michael Pavone <pavone@retrodev.com>
date Fri, 17 Apr 2015 17:50:47 -0700
parents 2308336790d4
children
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: ""
				}
				fold:with <- :acc :fun {
					acc <- fun: acc self
					acc <- _left fold: acc with: fun
					_right fold: acc with: fun
				}
			}
		}

		stringLit <- :_val {
			#{
				nodeType <- { _string }
				val <- _val
				stringIndent <- :indent {
					"\"" . val . "\""
				}
				string <- {
					stringIndent: ""
				}
				fold:with <- :acc :fun {
					fun: acc self
				}
			}
		}

		intLit:withBits:andBase:signed? <- :_val :_bits :_base :_signed? {
			#{
				nodeType <- { _int }
				val <- _val
				base <- _base
				bits <- _bits
				size <- { _bits / 8 }
				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: ""
				}
				fold:with <- :acc :fun {
					fun: acc self
				}
			}
		}
		
		symbol:withType <- :_name :_type {
			#{
				nodeType <- { _symbol }
				type <- _type
				name <- _name
				stringIndent <- :indent {
					_type value: :type {
						name . " (" . type . ")"
					} none: {
						name
					}
				}
				string <- {
					stringIndent: ""
				}
				fold:with <- :acc :fun {
					fun: acc self
				}
			}
		}

		symbol <- :_name {
			symbol: _name withType: (option none)
		}

		funcall:withArgs:hasReceiver? <- :_tocall :_args :_receiver? {
			#{
				nodeType <- { _call }
				tocall <- _tocall
				args <- _args
				hasReceiver? <- _receiver?
				llMessage? <- {
					(tocall nodeType) = _symbol && (tocall name) = "llMessage:withVars:andCode"
				}
				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: ""
				}
				fold:with <- :acc :fun {
					acc <- fun: acc self
					_args fold: acc with: :acc el {
						el fold: acc with: fun
					}
				}
			}
		}

		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: ""
				}
				fold:with <- :acc :fun {
					acc <- fun: acc self
					messages fold: acc with: :acc el {
						el fold: acc with: fun
					}
				}
			}
		}

		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: ""
				}
				fold:with <- :acc :fun {
					acc <- fun: acc self
					els fold: acc with: :acc el {
						el fold: acc with: fun
					}
				}
			}
		}

		assign:to <- :_expr :_sym {
			#{
				nodeType <- { _assignment }
				assign <- _expr
				to <- _sym
				stringIndent <- :indent {
					(to stringIndent: indent) . " <- " . (assign stringIndent: indent)
				}
				string <- {
					stringIndent: ""
				}
				fold:with <- :acc :fun {
					acc <- fun: acc self
					acc <- _sym fold: acc with: fun
					_expr fold: acc with: fun
				}
			}
		}

		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: ""
				}
				fold:with <- :acc :fun {
					acc <- fun: acc self
					expressions fold: acc with: :acc el {
						el fold: acc with: fun
					}
				}
			}
		}
	}
}