<commit_before>package main

type Function struct {
	Exists bool
	Loaded bool
	Import string
	Inline bool
	Data string
	
	Method bool
	
	Variadic bool
	
	Returns []Type
	Args []Type
}

func (ic *Compiler) ScanFunctionCall(name string) string {
	f := ic.DefinedFunctions[name]
	
	//TODO allow variadic arguments along with normal arguments.
	if f.Variadic {
		id := ic.Tmp("variadic")
		
		ic.Assembly("ARRAY ", id)
		for {
			value := ic.ScanExpression()
			ic.Assembly("PLACE ", id)
			ic.Assembly("PUT ", value)
			
			token := ic.Scan(0)
			if token != "," {
				if token != ")" {
					ic.RaiseError()
				}
				ic.NextToken = ")"
				break
			}
		}
	
		ic.Assembly("SHARE ", id)
	} else {
		for i := range f.Args {
			arg := ic.ScanExpression()
			
			if f.Args[i] != ic.ExpressionType {
				ic.RaiseError("Type mismatch! Argument ",i+1," of '"+name+"()' expects ",f.Args[i].Name,", got ",ic.ExpressionType.Name) 
			}
			
			ic.Assembly("%v %v", ic.ExpressionType.Push, arg)
			
			token := ic.Scan(0)
			if token != "," && token != ")" {
				ic.RaiseError()
			}
			if token == ")" {
				ic.NextToken = ")"
				break
			}
		}
		if f.Method && ic.Peek() != ")" {
			arg := ic.ScanExpression()
			if _, ok := ic.DefinedFunctions[name+"_m_"+ic.ExpressionType.Name]; !ok {
				ic.RaiseError("Method ",name," for type ",ic.ExpressionType.Name, "does not exist!")
			}
			
			//Hardcoded LEN optimisation.
			if name == "len" {
				ic.ExpressionType = Number
				return "#"+arg
			}
			
			ic.Assembly("%v %v", ic.ExpressionType.Push, arg)
			f = ic.DefinedFunctions[name+"_m_"+ic.ExpressionType.Name]
			name = name+"_m_"+ic.ExpressionType.Name
		}
	}
	
	ic.Assembly(ic.RunFunction(name))
	
	if len(f.Returns) > 0 {
		id := ic.Tmp("result")
		
		var ReturnType = f.Returns[0]
		
		
		ic.Assembly("%v %v", ReturnType.Pop, id)
		ic.ExpressionType = ReturnType
		
		return id
	}	
	return ""
}

func (ic *Compiler) ScanFunction() {
	var name string = ic.Scan(Name)
	
	ic.Assembly("FUNCTION ", name)
	ic.Scan('(')
	ic.GainScope()
	
	ic.function(name)
}

func (ic *Compiler) ScanNew() {
	var name string = ic.Scan(Name)
	
	ic.Assembly("FUNCTION ", name)
	ic.Scan('{')
	ic.GainScope()
	
	ic.SetFlag(New)
	ic.SetFlag(InMethod)
	ic.SetFlag(InFunction)
	
	ic.Assembly("PUSH ", len(ic.LastDefinedType.Detail.Elements))
	ic.Assembly("MAKE")
	ic.Assembly("GRAB ", ic.LastDefinedType.Name)
	ic.SetVariable(ic.LastDefinedType.Name, ic.LastDefinedType)
	
	ic.DefinedFunctions[name] = Function{Exists:true, Returns:[]Type{ic.LastDefinedType}}
}

func (ic *Compiler) ScanMethod() {
	var name string = ic.Scan(Name)
	name += "_m_"+ic.LastDefinedType.Name
	
	ic.Assembly("FUNCTION ", name)
	ic.Scan('(')
	ic.GainScope()
	
	ic.Assembly("%v %v", ic.LastDefinedType.Pop, ic.LastDefinedType.Name)
	ic.SetVariable(ic.LastDefinedType.Name, ic.LastDefinedType)
	
	ic.function(name)
	ic.SetFlag(InMethod)
}

func (ic *Compiler) function(name string) {
	var function Function
	
	//We need to reverse the POP's because of stack pain.
	if ic.Peek() != ")" {
		var toReverse []string
		for {
			//Identfy the type and add it to the function.
			var ArgumentType = ic.ScanSymbolicType()
		
			if ArgumentType == Variadic {
				function.Variadic = true
				ArgumentType = Array
			}
			function.Args = append(function.Args, ArgumentType)
		
			var name = ic.Scan(Name)
		
			ic.SetVariable(name, ArgumentType)
		
			toReverse = append(toReverse, ArgumentType.Pop+" "+name)
		
			token := ic.Scan(0)
		
			if token != "," {
				if token != ")" {
					ic.RaiseError()
				}
				break
			}
		}
		for i := len(toReverse)-1; i>=0; i-- {
			ic.Assembly(toReverse[i])
		}
	} else {
		ic.Scan(')')
	}
	
	
	token := ic.Scan(0)
	
	//Find out the return value.
	if token != "{" || (token == "{" && ic.Peek() == "}") {
	
		ic.NextToken = token
		var ReturnType = ic.ScanSymbolicType()
		
		function.Returns = append(function.Returns, ReturnType)
		
		if ReturnType == Number {
			ic.Scan(Name)
		}
		ic.Scan('{')
	}
	
	function.Exists = true
	
	ic.DefinedFunctions[name] = function
	
	ic.CurrentFunction = function
	
	ic.SetFlag(InFunction)
}<commit_msg>Better method handling and auto-type inferring for functions.<commit_after>package main

type Function struct {
	Exists bool
	Loaded bool
	Import string
	Inline bool
	Data string
	
	Method bool
	
	Variadic bool
	
	Returns []Type
	Args []Type
}

func (ic *Compiler) ScanFunctionCall(name string) string {
	f := ic.DefinedFunctions[name]
	
	//TODO allow variadic arguments along with normal arguments.
	if f.Variadic {
		id := ic.Tmp("variadic")
		
		ic.Assembly("ARRAY ", id)
		for {
			value := ic.ScanExpression()
			ic.Assembly("PLACE ", id)
			ic.Assembly("PUT ", value)
			
			token := ic.Scan(0)
			if token != "," {
				if token != ")" {
					ic.RaiseError()
				}
				ic.NextToken = ")"
				break
			}
		}
	
		ic.Assembly("SHARE ", id)
	} else if len(f.Args) > 0 {
		for i := range f.Args {
			arg := ic.ScanExpression()
			
			if f.Args[i] != ic.ExpressionType {
				if f.Args[i] == User {
					f.Args[i] = ic.ExpressionType
				} else {
					ic.RaiseError("Type mismatch! Argument ",i+1," of '"+name+"()' expects ",
						f.Args[i].Name,", got ",ic.ExpressionType.Name) 
				}
			}
			
			ic.Assembly("%v %v", ic.ExpressionType.Push, arg)
			
			token := ic.Scan(0)
			if token != "," && token != ")" {
				ic.RaiseError()
			}
			if token == ")" {
				ic.NextToken = ")"
				break
			}
		}
	} else {
		if f.Method && ic.Peek() != ")" {
			arg := ic.ScanExpression()
			if _, ok := ic.DefinedFunctions[name+"_m_"+ic.ExpressionType.Name]; !ok {
				ic.RaiseError("Method ",name," for type ",ic.ExpressionType.Name, "does not exist!")
			}
			
			//Hardcoded LEN optimisation.
			if name == "len" {
				ic.ExpressionType = Number
				return "#"+arg
			}
			
			ic.Assembly("%v %v", ic.ExpressionType.Push, arg)
			f = ic.DefinedFunctions[name+"_m_"+ic.ExpressionType.Name]
			name = name+"_m_"+ic.ExpressionType.Name
		}
	}
	
	ic.Assembly(ic.RunFunction(name))
	
	if len(f.Returns) > 0 {
		id := ic.Tmp("result")
		
		var ReturnType = f.Returns[0]
		
		
		ic.Assembly("%v %v", ReturnType.Pop, id)
		ic.ExpressionType = ReturnType
		
		return id
	}	
	return ""
}

func (ic *Compiler) ScanFunction() {
	var name string = ic.Scan(Name)
	
	ic.Assembly("FUNCTION ", name)
	ic.Scan('(')
	ic.GainScope()
	
	ic.function(name)
}

func (ic *Compiler) ScanNew() {
	var name string = ic.Scan(Name)
	
	ic.Assembly("FUNCTION ", name)
	ic.Scan('{')
	ic.GainScope()
	
	ic.SetFlag(New)
	ic.SetFlag(InMethod)
	ic.SetFlag(InFunction)
	
	ic.Assembly("PUSH ", len(ic.LastDefinedType.Detail.Elements))
	ic.Assembly("MAKE")
	ic.Assembly("GRAB ", ic.LastDefinedType.Name)
	ic.SetVariable(ic.LastDefinedType.Name, ic.LastDefinedType)
	
	ic.DefinedFunctions[name] = Function{Exists:true, Returns:[]Type{ic.LastDefinedType}}
}

func (ic *Compiler) ScanMethod() {
	var name string = ic.Scan(Name)
	name += "_m_"+ic.LastDefinedType.Name
	
	ic.Assembly("FUNCTION ", name)
	ic.Scan('(')
	ic.GainScope()
	
	ic.Assembly("%v %v", ic.LastDefinedType.Pop, ic.LastDefinedType.Name)
	ic.SetVariable(ic.LastDefinedType.Name, ic.LastDefinedType)
	
	ic.function(name)
	ic.SetFlag(InMethod)
	
	f := ic.DefinedFunctions[name]
	f.Method = true
	ic.DefinedFunctions[name] = f
}

func (ic *Compiler) function(name string) {
	var function Function
	
	//We need to reverse the POP's because of stack pain.
	if ic.Peek() != ")" {
		var toReverse []string
		for {
			//Identfy the type and add it to the function.
			var ArgumentType = ic.ScanSymbolicType()
		
			if ArgumentType == Variadic {
				function.Variadic = true
				ArgumentType = Array
			}
			function.Args = append(function.Args, ArgumentType)
		
			var name = ic.Scan(Name)
		
			ic.SetVariable(name, ArgumentType)
		
			toReverse = append(toReverse, ArgumentType.Pop+" "+name)
		
			token := ic.Scan(0)
		
			if token != "," {
				if token != ")" {
					ic.RaiseError()
				}
				break
			}
		}
		for i := len(toReverse)-1; i>=0; i-- {
			ic.Assembly(toReverse[i])
		}
	} else {
		ic.Scan(')')
	}
	
	
	token := ic.Scan(0)
	
	//Find out the return value.
	if token != "{" || (token == "{" && ic.Peek() == "}") {
	
		ic.NextToken = token
		var ReturnType = ic.ScanSymbolicType()
		
		function.Returns = append(function.Returns, ReturnType)
		
		if ReturnType == Number {
			ic.Scan(Name)
		}
		ic.Scan('{')
	}
	
	function.Exists = true
	function.Method = true
	
	ic.DefinedFunctions[name] = function
	
	ic.CurrentFunction = function
	
	ic.SetFlag(InFunction)
}
{'fraction_non_alphanumeric': 0.16101295641931684, 'fraction_numerical': 0.002237926972909305, 'mean_word_length': 3.0724220623501197, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 8, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '3551573', 'n_tokens_mistral': 3613, 'n_tokens_neox': 3048, 'n_words': 649}