Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

for some help with its use #53

Open
JeffreySarnoff opened this issue Nov 7, 2017 · 3 comments
Open

for some help with its use #53

JeffreySarnoff opened this issue Nov 7, 2017 · 3 comments

Comments

@JeffreySarnoff
Copy link

JeffreySarnoff commented Nov 7, 2017

I remembered this work -- still a fan.
Users want me to provide a simple wrapping macro that engages safer Int types.

Ideally,

@safer_integers begin
    # code
end
@safer_integers begin
    include("my_toplevel_sourcefile")
end

and each occurance of Int, UInt, Int8, ..., Int128, UInt8, ..., UInt128 is replaced (prepending "Safe").

Any direction or helpful hints?

@fcard
Copy link
Owner

fcard commented Nov 8, 2017

The second example can't be done, unfortunately. File inclusion happens after macroexpansion.

This is tricky and maybe impossible to get completely right, there are many corner cases to consider.
But as a starter, I would...

using ExpressionPatterns.Dispatch
using SaferIntegers

## Syntax

# Singular statement
@macromethod safe_integers(x) esc(safe_integers(x))

# Block statement
@macromethod safe_integers(begin *{statements} end) esc(quote
  $(safe_integers.(statements)...)
end)


## Substitution cases

# Generic expression case
@metafunction safe_integers(:T{x,Expr}) Expr(x.head, safe_integers.(x.args)...)

# Leaf cases
@metafunction safe_integers(x) :(@safe_int($x))

# Type assertion
@metafunction safe_integers(x::T) :($x::@safe_int(T))

# Module case (ignore?)
@metafunction safe_integers(M.x) :($M.$x)

#...


## Substitutions

# No substitution:
@macromethod safe_int(x) x

# Literal substitution:
@macromethod safe_int(:T{x,Int8})  SafeInt8(x)
@macromethod safe_int(:T{x,Int16}) SafeInt16(x)
@macromethod safe_int(:T{x,Int32}) SafeInt32(x)
@macromethod safe_int(:T{x,Int64}) SafeInt64(x)
#...

# Type substitution:
@macromethod safe_int(:L{Int8})  SafeInt8
@macromethod safe_int(:L{Int16}) SafeInt16
@macromethod safe_int(:L{Int32}) SafeInt32
@macromethod safe_int(:L{Int64}) SafeInt64
#...

The above will give you:

julia> @safe_integers(1 + 2) |> typeof
SaferIntegers.SafeInt64

julia> @safe_integers(1) |> typeof
SaferIntegers.SafeInt64

julia> @safe_integers(Int8)
SaferIntegers.SafeInt8

julia> @safe_integers begin
         let x::Int8 = 10
           println(typeof(x))
         end
       end
SaferIntegers.SafeInt8

There are a lot more considerations to take, but this is a start. Feel free to ask questions (I am a bit busy right now so I may take a bit to answer but I will definitely get to it!)

@JeffreySarnoff
Copy link
Author

What about using Tokenize and converting tokens for "Int64" into tokens for "SafeInt64"?
I'm not sure what to do with that since it is only source text that can be tokenized that way (right?).
People want to filter their modules through SafeIntegers so the Ints get Safe. Does the macro stuff apply to a package that has been precompiled? thanks for time.

@fcard
Copy link
Owner

fcard commented Nov 16, 2017

I am not sure how Tokenize would work. I am also not sure what you mean by the macro applying to a precompiled package. If you're asking if you can use macros in a package meant to precompiled, then yes; in fact this very package is precompilable, and it both uses and exports macros.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants