PageRenderTime 28ms CodeModel.GetById 17ms RepoModel.GetById 0ms app.codeStats 0ms

/source/core/ast/FuncDecl.ooc

http://github.com/nddrylliog/oc
Unknown | 152 lines | 124 code | 28 blank | 0 comment | 0 complexity | 95cfe8c6dc32b1e0fca3f6e772658488 MD5 | raw file
  1. import structs/[ArrayList, HashMap]
  2. import Expression, Statement, Scope, Var, Type, Access, Return, Call
  3. import middle/Resolver
  4. FuncDecl: class extends Expression {
  5. global := false
  6. resolved := false
  7. body := Scope new()
  8. args := HashMap<String, Var> new()
  9. retType := VoidType new()
  10. _type: FuncType
  11. externName: String { get set }
  12. name: String { get set }
  13. // for closures
  14. accesses: ArrayList<Access>
  15. init: func ~fDecl {
  16. name = ""
  17. externName = null
  18. _type = FuncType new(this)
  19. }
  20. anon?: func -> Bool {
  21. name empty?()
  22. }
  23. markAccess: func (acc: Access) {
  24. if(!accesses) {
  25. accesses = ArrayList<Access> new()
  26. } else {
  27. for(acc2 in accesses) {
  28. if(acc name == acc2 name) return
  29. }
  30. }
  31. "%s is accessing %s" printfln(toString(), acc toString())
  32. accesses add(acc)
  33. }
  34. resolve: func (task: Task) {
  35. task queueList(args)
  36. task queue(retType)
  37. resolved = true // artificial testing
  38. task queue(body)
  39. match (task parent node) {
  40. case c: Call =>
  41. "Parent of %s is call %s" printfln(toString(), c toString())
  42. while(c subject ref == null) {
  43. "ref = %s" printfln(c subject ref ? c subject ref toString() : "(nil)")
  44. "C subject's ref is null, yielding" println()
  45. task parent queue(c subject)
  46. "Back here!" println()
  47. }
  48. inferType(c)
  49. }
  50. autoReturn(task)
  51. }
  52. inferType: func (outerCall: Call) {
  53. "outerCall = %s" printfln(outerCall toString())
  54. // idx is our position in the call arguments, or -1 if we're not an argument of outerCall
  55. idx := outerCall args indexOf(this)
  56. if(idx == -1) {
  57. "Decl %s is a child of task for call %s but it's not in its arguments!" printfln(toString(), outerCall toString())
  58. return
  59. }
  60. "idx = %d" printfln(idx)
  61. // callRef is the Var that our outer call's subject has been resolved to
  62. callRef := outerCall subject ref
  63. if(!callRef getType() instanceOf?(FuncType)) {
  64. Exception new("Should never happen: outer call %s was resolved to something that's not a function! (ie. %s)" \
  65. format(outerCall toString(), callRef getType() toString())) throw()
  66. }
  67. "callRef = %s" printfln(callRef toString())
  68. // callProto is the FuncDecl which defines the argument types of the reference of the outer call
  69. callProto := callRef getType() as FuncType proto
  70. "callProto = %s" printfln(callRef toString())
  71. // outerType is the type that the outer call expects us to be. Our actual type is getType()
  72. outerType := callProto args get(callProto args getKeys() get(idx)) getType()
  73. if(!outerType instanceOf?(FuncType)) {
  74. Exception new("Passing a function (ie. %s) to a %s where expecting a %s (%s)" format(toString(), callProto toString(), outerType toString(), outerType class name)) throw()
  75. }
  76. "outerType = %s" printfln(outerType toString())
  77. outerProto := outerType as FuncType proto
  78. "outerProto = %s" printfln(outerProto toString())
  79. if(outerProto args size != args size) {
  80. Exception new("Function %s is not compatible with type %s" format(toString(), outerProto toString())) throw()
  81. }
  82. "Inferring return type of %s to be %s" printfln(toString(), outerProto retType toString())
  83. retType = outerProto retType
  84. }
  85. autoReturn: func (task: Task) {
  86. if(!retType void?()) {
  87. list := body body
  88. if(list empty?()) {
  89. "Expected return expression in non-void function %s" printfln(name)
  90. exit(1)
  91. } else {
  92. last := list last()
  93. if(last class == Return) {
  94. // all good
  95. } else if(last instanceOf?(Expression)) {
  96. list set(list size - 1, Return new(last as Expression))
  97. } else {
  98. "Expected return expression in non-void function %s" printfln(name)
  99. exit(1)
  100. }
  101. }
  102. }
  103. }
  104. resolveAccess: func (acc: Access, task: Task, suggest: Func (Var)) {
  105. v := args get(acc name)
  106. if(v) suggest(v)
  107. }
  108. toString: func -> String {
  109. b := Buffer new()
  110. b append("func (")
  111. first := true
  112. for(arg in args) {
  113. if(first) first = false
  114. else b append(", ")
  115. b append(arg toString())
  116. }
  117. b append(") -> ")
  118. b append(retType toString())
  119. b toString()
  120. }
  121. getType: func -> Type {
  122. _type
  123. }
  124. }