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  }