view modules/symbols.tp @ 331:61f5b794d939

Breaking change: method call syntax now always uses the syntactic receiver as the actual receiver. This makes its behavior different from function call syntax, but solves some problems with methods being shadowed by local variables and the like.
author Michael Pavone <pavone@retrodev.com>
date Sat, 28 Mar 2015 14:21:04 -0700
parents aea99b93cf2f
children
line wrap: on
line source

{
	_null <- #{
		find:else <- :_ :else {
			else:
		}
		ifDefined:else <- :name ifdef :else {
			else:
		}
	}
	_local <- 0
	_closedover <- 1
	_upvar <- 2
	_method <- 3
	_self <- 4
	_parent <- 5

	_nextMethodId <- 0
	_method <- :_name {
		_id <- _nextMethodId
		_nextMethodId <- _id + 1
		#{
			name <- { _name }
			id <- { _id }
			string <- { "method " . _name . "(" . _id . ")" }
			isMethod? <- { true }
			isLocal? <- { false }
		}
	}
	_local <- :_name _def {
		#{
			name <- { _name }
			string <- { "local " . _name }
			def <- { _def }
			isMethod? <- { false }
			closedOver? <- false
			isLocal? <- { true }
		}
	}
	_upvar <- :parent {
		if: (parent isLocal?) {
			parent closedOver?!: true
			#{
				name <- { parent name }
				def <- { parent def }
				closedOver? <- { parent closedOver? }
				isMethod? <- { parent isMethod? }
				string <- { "upvar " . name}
				isLocal? <- { false }
				depth <- 1
			}
		} else: {
			parent depth!: (parent depth) + 1
		}
	}
	#{
		nullTable <- { _null }

		tableWithParent <- :_parent {
			_symbols <- dict hash
			#{
				ifDefined:else <- :name ifdef :else {
					_symbols ifget: name :sym {
						ifdef: sym
					} else: {
						_parent ifDefined: name :sym {
							ifdef: (_upvar: sym)
						} else: else
					}
				}
				find:else <- :name :else {
					_symbols get: name else: {
						_parent ifDefined: name :sym {
							if: (sym isMethod?) {
								//TODO: methods on parent objects
								sym
							} else: {
								_upvar: sym
							}
						} else: {
							else:
						}
					}
				}
				defineMethod <- :name {
					_symbols get: name else: {
						_symbols set: name (_method: name)
					}
					self
				}
				define <- :name def {
					s <- (_local: name def)
					_symbols set: name s
					s
				}
				find:elseDefine <- :name :def {
					find: name else: {
						define: name def
					}
				}
				print <- {
					foreach: _symbols :name info {
						print: name . ": " . info . "\n"
					}
				}
			}
		}

		table <- {
			tableWithParent: _null
		}

		buildMethodTable <- :tree {
			_object <- ast obj
			_assignment <- ast assignment
			_call <- ast call

			tree fold: table with: :acc el {
				if: (el nodeType) = _object {
					(el messages) fold: acc with: :acc msg {
						if: (msg nodeType) = _assignment {
							acc defineMethod: ((msg to) name)
						} else: {
							if: (msg nodeType) = _call && (msg llMessage?) {
								acc defineMethod: (((msg args) value) name)
							}
						}
						acc
					}
				} else: {
					acc
				}
			}
		}
	}
}