package main import ( "fmt" "math" "math/rand" ) func opAdd(val1, val2 value) value { return value{tp: typeNumber, num: toNumber(val1) + toNumber(val2)} } func opSub(val1, val2 value) value { return value{tp: typeNumber, num: toNumber(val1) - toNumber(val2)} } func opMul(val1, val2 value) value { return value{tp: typeNumber, num: toNumber(val1) * toNumber(val2)} } func opDiv(val1, val2 value) value { num1, num2 := toNumber(val1), toNumber(val2) if num2 == 0 { panic(fmt.Errorf("div: %s (%f / %f)", errDivisionByZero, num1, num2)) } return value{tp: typeNumber, num: num1 / num2} } func opMod(val1, val2 value) value { num1, num2 := toNumber(val1), toNumber(val2) if num2 == 0 { panic(fmt.Errorf("mod: %s (%f %% %f)", errDivisionByZero, num1, num2)) } return value{tp: typeNumber, num: math.Mod(num1, num2)} } func opEq(val1, val2 value) value { if isNumber(val1) && isNumber(val2) { return value{tp: typeBool, b: toNumber(val1) == toNumber(val2)} } if isBool(val1) && isBool(val2) { return value{tp: typeBool, b: toBool(val1) == toBool(val2)} } if isWord(val1) && isWord(val2) { return value{tp: typeBool, b: escapeWord(val1.word) == escapeWord(val2.word)} } panic(fmt.Errorf("eq: %s (%s == %s)", errIllegalOperandType, toString(val1), toString(val2))) } func opGt(val1, val2 value) value { if isNumber(val1) && isNumber(val2) { return value{tp: typeBool, b: toNumber(val1) > toNumber(val2)} } if isBool(val1) && isBool(val2) { return value{tp: typeBool, b: toBool(val1) || !toBool(val2)} } if isWord(val1) && isWord(val2) { return value{tp: typeBool, b: escapeWord(val1.word) > escapeWord(val2.word)} } panic(fmt.Errorf("gt: %s (%s > %s)", errIllegalOperandType, toString(val1), toString(val2))) } func opLt(val1, val2 value) value { if isNumber(val1) && isNumber(val2) { return value{tp: typeBool, b: toNumber(val1) < toNumber(val2)} } if isBool(val1) && isBool(val2) { return value{tp: typeBool, b: !toBool(val1) || toBool(val2)} } if isWord(val1) && isWord(val2) { return value{tp: typeBool, b: escapeWord(val1.word) < escapeWord(val2.word)} } panic(fmt.Errorf("lt: %s (%s < %s)", errIllegalOperandType, toString(val1), toString(val2))) } func opAnd(val1, val2 value) value { return value{tp: typeBool, b: toBool(val1) && toBool(val2)} } func opOr(val1, val2 value) value { return value{tp: typeBool, b: toBool(val1) || toBool(val2)} } func opNot(val1 value) value { return value{tp: typeBool, b: !toBool(val1)} } func opRandom(val1 value) value { return value{tp: typeNumber, num: toNumber(val1) * rand.Float64()} } func opInt(val1 value) value { return value{tp: typeNumber, num: math.Floor(toNumber(val1))} } func opSqrt(val1 value) value { num1 := toNumber(val1) if num1 < 0 { panic(fmt.Errorf("sqrt: %s (%f)", errNegativeSquareRoot, num1)) } return value{tp: typeNumber, num: math.Sqrt(num1)} }