// Generic handler for retrieval of all variable types // This is made generic through the errorName parameter which is the fully // qualified name of the variable for error printing purposes // You can better understand how this works by looking at the retrieval // methods for arrays and objects func GetVariableGeneric(varName string, errorName string, lineno int) Value { // Check local table in, value := GetFromScope(varName) if in && value.Type == VALUE_UNDEFINED && !value.Written { log.ValueError(lineno, errorName) } if in { return value } // Check the global table in, value = GetFromGlobal(varName) if in && value.Type == VALUE_UNDEFINED && !value.Written { log.ValueError(lineno, errorName) } if in { return value } // At this point the value must be in neither table log.ValueError(lineno, errorName) return Value{Written: false, Type: VALUE_UNDEFINED, Line: lineno} }
func GetArrayMember(arrayName string, index int, lineno int) Value { // Find the array itself array := GetVariable(arrayName, lineno) if array.Type == VALUE_UNDEFINED { log.ValueError(lineno, arrayName) } if array.Type != VALUE_ARRAY { log.TypeViolation(lineno) return Value{Type: VALUE_UNDEFINED, Line: lineno} } oldScope := Scope Scope = array.Value.(map[string]Value) keyValue := GetVariableGeneric(strconv.Itoa(index), fmt.Sprintf("%s[%d]", arrayName, index), lineno) Scope = oldScope return Value{Type: keyValue.Type, Value: keyValue.Value, Written: keyValue.Written, Line: keyValue.Line} }
func GetObjectMember(objectName string, keyName string, lineno int) Value { // Find the object itself object := GetVariable(objectName, lineno) if object.Type == VALUE_UNDEFINED { log.ValueError(lineno, objectName) } if object.Type != VALUE_OBJECT { log.TypeViolation(lineno) return Value{Type: VALUE_UNDEFINED, Line: lineno} } // Set this object's fields as the new scope then restore it later // This is, quite possibly, the smartest thing I have ever devised. Lol. Lol. Lol. // Full of himself meter = 10/10. Chance of anyone ever seeing this: 1/10 oldScope := Scope Scope = object.Value.(map[string]Value) keyValue := GetVariableGeneric(keyName, objectName+"."+keyName, lineno) Scope = oldScope // All other error handling is done in gvg() return Value{Type: keyValue.Type, Value: keyValue.Value, Written: keyValue.Written, Line: keyValue.Line} }