Skip to content

Commit 824f290

Browse files
committed
Unitful-like unit parsing macro
1 parent 50f7a79 commit 824f290

File tree

1 file changed

+48
-4
lines changed

1 file changed

+48
-4
lines changed

src/uparse.jl

Lines changed: 48 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,8 @@ import ..constructorof
44
import ..DEFAULT_QUANTITY_TYPE
55
import ..DEFAULT_DIM_TYPE
66
import ..DEFAULT_VALUE_TYPE
7-
import ..Units: UNIT_SYMBOLS
7+
import ..Units: UNIT_SYMBOLS, UNIT_VALUES
8+
import ..Constants: CONSTANT_SYMBOLS, CONSTANT_VALUES
89
import ..Constants
910

1011
function _generate_units_import()
@@ -34,11 +35,11 @@ the quantity corresponding to the speed of light multiplied by Hertz,
3435
squared.
3536
"""
3637
function uparse(s::AbstractString)
37-
return as_quantity(eval(Meta.parse(s)))::DEFAULT_QUANTITY_TYPE
38+
return as_quantity(eval(map_to_scope(Meta.parse(s))))::DEFAULT_QUANTITY_TYPE
3839
end
3940

4041
as_quantity(q::DEFAULT_QUANTITY_TYPE) = q
41-
as_quantity(x::Number) = convert(DEFAULT_QUANTITY_TYPE, x)
42+
as_quantity(x::Number) = convert(DEFAULT_QUANTITY_TYPE, x)
4243
as_quantity(x) = error("Unexpected type evaluated: $(typeof(x))")
4344

4445
"""
@@ -54,7 +55,50 @@ the quantity corresponding to the speed of light multiplied by Hertz,
5455
squared.
5556
"""
5657
macro u_str(s)
57-
return esc(Meta.parse(s))
58+
ex = Meta.parse(s)
59+
return esc(map_to_scope(ex))
60+
end
61+
62+
function map_to_scope(ex::Expr)
63+
if ex.head == :call
64+
ex.args[2:end] = map(map_to_scope, ex.args[2:end])
65+
return ex
66+
elseif ex.head == :tuple
67+
ex.args[:] = map(map_to_scope, ex.args)
68+
return ex
69+
elseif ex.head == :.
70+
if ex.args[1] == :Constants
71+
@assert ex.args[2] isa QuoteNode
72+
return lookup_constant(ex.args[2].value)
73+
else
74+
return ex
75+
end
76+
else
77+
throw(ArgumentError("Unexpected expression: $ex. Only `:call`, `:tuple`, and `:.` are expected."))
78+
return ex
79+
end
80+
end
81+
function map_to_scope(sym::Symbol)
82+
if sym in UNIT_SYMBOLS
83+
return lookup_unit(sym)
84+
elseif sym in CONSTANT_SYMBOLS
85+
throw(ArgumentError("Found the symbol $sym. To access constants in a unit expression, access the `Constants` module. For example, `u\"Constants.h\"`."))
86+
return sym
87+
else
88+
throw(ArgumentError("Symbol $sym not found in `Units` or `Constants`."))
89+
return sym
90+
end
91+
end
92+
function map_to_scope(ex)
93+
return ex
94+
end
95+
function lookup_unit(ex::Symbol)
96+
i = findfirst(==(ex), UNIT_SYMBOLS)::Int
97+
return UNIT_VALUES[i]
98+
end
99+
function lookup_constant(ex::Symbol)
100+
i = findfirst(==(ex), CONSTANT_SYMBOLS)::Int
101+
return CONSTANT_VALUES[i]
58102
end
59103

60104
end

0 commit comments

Comments
 (0)