master-thesis/package/src/ExpressionProcessing.jl
Daniel 20fcbab4ca
Some checks are pending
CI / Julia ${{ matrix.version }} - ${{ matrix.os }} - ${{ matrix.arch }} - ${{ github.event_name }} (x64, ubuntu-latest, 1.6) (push) Waiting to run
CI / Julia ${{ matrix.version }} - ${{ matrix.os }} - ${{ matrix.arch }} - ${{ github.event_name }} (x64, ubuntu-latest, pre) (push) Waiting to run
CI / Julia ${{ matrix.version }} - ${{ matrix.os }} - ${{ matrix.arch }} - ${{ github.event_name }} (x64, ubuntu-latest, 1.10) (push) Waiting to run
concept and design: added transpiler section
2025-04-06 13:59:14 +02:00

140 lines
3.9 KiB
Julia

module ExpressionProcessing
export expr_to_postfix, is_binary_operator
export PostfixType
export Operator, ADD, SUBTRACT, MULTIPLY, DIVIDE, POWER, ABS, LOG, EXP, SQRT
export ElementType, EMPTY, FLOAT32, OPERATOR, INDEX
export ExpressionElement
@enum Operator ADD=1 SUBTRACT=2 MULTIPLY=3 DIVIDE=4 POWER=5 ABS=6 LOG=7 EXP=8 SQRT=9
@enum ElementType EMPTY=0 FLOAT32=1 OPERATOR=2 INDEX=3
struct ExpressionElement
Type::ElementType
Value::Int32 # Reinterpret the stored value to type "ElementType" when using it
end
const PostfixType = Vector{ExpressionElement}
"
Converts a julia expression to its postfix notation.
NOTE: All 64-Bit values will be converted to 32-Bit. Be aware of the lost precision
"
function expr_to_postfix(expr::Expr)::PostfixType
postfix = PostfixType()
@inbounds operator = get_operator(expr.args[1])
@inbounds for j in 2:length(expr.args)
arg = expr.args[j]
if typeof(arg) === Expr
append!(postfix, expr_to_postfix(arg))
elseif typeof(arg) === Symbol # variables/parameters
# maybe TODO: replace the parameters with their respective values, as this might make the expr evaluation faster
exprElement = convert_to_ExpressionElement(convert_var_to_int(arg))
push!(postfix, exprElement)
else
exprElement = convert_to_ExpressionElement(convert(Float32, arg))
push!(postfix, exprElement)
end
# only add operator if at least 2 values are added. For the case where another expression is added first, we check if we are at the first iteration or not ( j != 2)
if length(postfix) >= 2 && j != 2
exprElement = convert_to_ExpressionElement(operator)
push!(postfix, exprElement)
end
end
# For the case this expression has an operator that only takes in a single value like "abs(x)"
if length(postfix) == 1
push!(postfix, convert_to_ExpressionElement(operator))
end
return postfix
end
function get_operator(op::Symbol)::Operator
if op == :+
return ADD
elseif op == :-
return SUBTRACT
elseif op == :*
return MULTIPLY
elseif op == :/
return DIVIDE
elseif op == :^
return POWER
elseif op == :abs
return ABS
elseif op == :log
return LOG
elseif op == :exp
return EXP
elseif op == :sqrt
return SQRT
elseif op == :powabs
return POWER # TODO: Fix this
else
throw("Operator unknown")
end
end
"Extracts the number from a variable/parameter and returns it. If the symbol is a parameter ```pn```, the resulting value will be negativ.
```x0 and p0``` are not allowed."
function convert_var_to_int(var::Symbol)::Int32
varStr = String(var)
number = parse(Int32, SubString(varStr, 2))
if varStr[1] == 'p'
number = -number
end
return number
end
function convert_to_ExpressionElement(element::Int32)::ExpressionElement
value = reinterpret(Int32, element)
return ExpressionElement(INDEX, value)
end
function convert_to_ExpressionElement(element::Int64)::ExpressionElement
value = reinterpret(Int32, convert(Int32, element))
return ExpressionElement(INDEX, value)
end
function convert_to_ExpressionElement(element::Float32)::ExpressionElement
value = reinterpret(Int32, element)
return ExpressionElement(FLOAT32, value)
end
function convert_to_ExpressionElement(element::Float64)::ExpressionElement
value = reinterpret(Int32, convert(Float32, element))
return ExpressionElement(FLOAT32, value)
end
function convert_to_ExpressionElement(element::Operator)::ExpressionElement
value = reinterpret(Int32, element)
return ExpressionElement(OPERATOR, value)
end
function is_binary_operator(operator::Operator)::Bool
if operator == ADD
return true
elseif operator == SUBTRACT
return true
elseif operator == MULTIPLY
return true
elseif operator == DIVIDE
return true
elseif operator == POWER
return true
elseif operator == ABS
return false
elseif operator == LOG
return false
elseif operator == EXP
return false
elseif operator == SQRT
return false
else
throw(ArgumentError("Unknown operator '$operator'. Cannot determine if it is binary or not."))
end
end
end