github.com/arnodel/golua@v0.0.0-20230215163904-e0b5347eaaa1/ast/functioncall.go (about) 1 package ast 2 3 // TODO: the FunctionCall / BFunctionCall distinction is awkward. Find a better 4 // expression of the difference. 5 6 // A BFunctionCall is an expression node that represents a function call 7 // surrounded by brackets. This changes the semantics of the call in some 8 // situations (e.g. ellipsis, tail calls). 9 // 10 // For example: 11 // 12 // return f(x) -- this may return multiple values and will be subject to TCO 13 // return (f(x)) -- this will only return one single value and will not be subject to TCO 14 type BFunctionCall struct { 15 Location 16 Target ExpNode 17 Method Name 18 Args []ExpNode 19 } 20 21 var _ ExpNode = BFunctionCall{} 22 23 // A FunctionCall is an expression node that represents a function call. 24 type FunctionCall struct { 25 *BFunctionCall 26 } 27 28 var _ ExpNode = FunctionCall{} 29 var _ TailExpNode = FunctionCall{} 30 var _ Stat = FunctionCall{} 31 32 // NewFunctionCall returns a FunctionCall instance representing the call of 33 // <target> with <args>. The <method> arg should be non-nil if the call syntax 34 // included ":", e.g. stack:pop(). 35 func NewFunctionCall(target ExpNode, method Name, args []ExpNode) FunctionCall { 36 // TODO: fix this by creating an Args node 37 loc := target.Locate() 38 if len(args) > 0 { 39 loc = MergeLocations(loc, args[len(args)-1]) 40 } else if method.Val != "" { 41 loc = MergeLocations(loc, method) 42 } 43 return FunctionCall{&BFunctionCall{ 44 Location: loc, 45 Target: target, 46 Method: method, 47 Args: args, 48 }} 49 } 50 51 // ProcessExp uses the given ExpProcessor to process the receiver. 52 func (f FunctionCall) ProcessExp(p ExpProcessor) { 53 p.ProcessFunctionCallExp(f) 54 } 55 56 // ProcessTailExp uses the give TailExpProcessor to process the receiver. 57 func (f FunctionCall) ProcessTailExp(p TailExpProcessor) { 58 p.ProcessFunctionCallTailExp(f) 59 } 60 61 // ProcessStat uses the given StatProcessor to process the receiver. 62 func (f FunctionCall) ProcessStat(p StatProcessor) { 63 p.ProcessFunctionCallStat(f) 64 } 65 66 // InBrackets turns the receiver into a BFunctionCall. 67 func (f FunctionCall) InBrackets() *BFunctionCall { 68 return f.BFunctionCall 69 } 70 71 // ProcessExp uses the given ExpProcessor to process the receiver. 72 func (f BFunctionCall) ProcessExp(p ExpProcessor) { 73 p.ProcessBFunctionCallExp(f) 74 } 75 76 // func (f BFunctionCall) MethodLocation() Location { 77 // // If we have a method, that's going to be the location, else if the call if 78 // // of the form "a.x()" then point to "x". 79 // if f.Method.Val != "" { 80 // return f.Method.Locate() 81 // } 82 // if e, ok := f.Target.(IndexExp); ok { 83 // return e.Idx.Locate() 84 // } 85 // return f.Location 86 // } 87 88 // HWrite prints a tree representation of the node. 89 func (f BFunctionCall) HWrite(w HWriter) { 90 w.Writef("call") 91 w.Indent() 92 w.Next() 93 w.Writef("target: ") 94 // w.Indent() 95 f.Target.HWrite(w) 96 // w.Dedent() 97 if f.Method.Val != "" { 98 w.Next() 99 w.Writef("method: %s", f.Method) 100 } 101 for i, arg := range f.Args { 102 w.Next() 103 w.Writef("arg_%d: ", i) 104 arg.HWrite(w) 105 } 106 w.Dedent() 107 }