Nothing Special   »   [go: up one dir, main page]

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

Term rewriting macros: not working when declared inside template #7214

Open
mratsim opened this issue Feb 13, 2018 · 2 comments
Open

Term rewriting macros: not working when declared inside template #7214

mratsim opened this issue Feb 13, 2018 · 2 comments

Comments

@mratsim
Copy link
Collaborator
mratsim commented Feb 13, 2018

This works

proc addmod[T: SomeInteger](a, b, modulus: T): T {.noSideEffect.}=
  ## Modular addition

  let a_m = if a < modulus: a
            else: a mod modulus
  if b == 0:
    return a_m
  let b_m = if b < modulus: b
            else: b mod modulus

  let b_from_m = modulus - b_m
  if a_m >= b_from_m:
    result = a_m - b_from_m
  else:
    result = modulus - b_from_m + a_m

## Notice the TRM in global scope
template trmAddMod{a + b}(a, b): auto =
  addmod(a, b, 12)

template modular[T: SomeInteger](modulus: T, body: untyped): untyped =
  body

proc main() =
  let
    a = 10
    b = 3

  modular(12):
    let u = a + b

  echo u
  echo addmod(a,b,12)
  echo u == addmod(a, b, 12)

main()

This doesn't

proc addmod[T: SomeInteger](a, b, modulus: T): T {.noSideEffect.}=
  ## Modular addition

  let a_m = if a < modulus: a
            else: a mod modulus
  if b == 0:
    return a_m
  let b_m = if b < modulus: b
            else: b mod modulus

  let b_from_m = modulus - b_m
  if a_m >= b_from_m:
    result = a_m - b_from_m
  else:
    result = modulus - b_from_m + a_m


## Notice the TRM in local scope
template modular[T: SomeInteger](modulus: T, body: untyped): untyped =
  template trmAddMod{a + b}(a, b): auto =
    addmod(a, b, 12)
  body

proc main() =
  let
    a = 10
    b = 3

  modular(12):
    let u = a + b

  echo u
  echo addmod(a,b,12)
  echo u == addmod(a, b, 12)

main()
@mratsim
Copy link
Collaborator Author
mratsim commented Feb 13, 2018

Note, changing "template" to macro solves the issue. I suppose the template replacement happens after the term-rewriting pass which is too late.

@mratsim
Copy link
Collaborator Author
mratsim commented Oct 20, 2018

I have a new use-case for scoped term-rewriting macro.

I'm refactoring Arraymancer backend, by default the new backend assumes that all raw pointer accesses are aligned and hints the compiler as such with:

proc builtin_assume_aligned[T](data: ptr T, n: csize): ptr T {.importc: "__builtin_assume_aligned", noDecl.}

However when interfacing with external buffers that may not be aligned (Numpy) it is needed to not assume anything. Adding an is_aligned static bool (assume_aligned only works if there is no runtime dispatch) to all procs like +, -, == ...

However by having a term-rewriting scope, we could neatly recursively rewrite all operations in that scope to not assume they are aligned by default:

import macros

proc unsafe_raw_data*(x: int, aligned: static bool = true): int {.inline.} =
  when aligned:
    echo "Aligned"
  else:
    echo "Unaligned"

macro raw_data_unaligned*(body: untyped): untyped =
  ## Within this code block, all raw data accesses will not be
  ## assumed aligned by default.
  template rewrite_unsafe_raw_data{unsafe_raw_data(t)}(t): auto =
    unsafe_raw_data(t, aligned = false)
  body

However, while I said that in the previous comment we could use macro instead of template to make the TRM works, once declared it "escapes" its block.

Test case:

proc addmod[T: SomeInteger](a, b, modulus: T): T {.noSideEffect.}=
  ## Modular addition

  let a_m = if a < modulus: a
            else: a mod modulus
  if b == 0:
    return a_m
  let b_m = if b < modulus: b
            else: b mod modulus

  let b_from_m = modulus - b_m
  if a_m >= b_from_m:
    result = a_m - b_from_m
  else:
    result = modulus - b_from_m + a_m


## Notice the TRM in local scope
macro modular[T: SomeInteger](modulus: T, body: untyped): untyped =
  block:
    template trmAddMod{a + b}(a, b): auto =
      addmod(a, b, 12)
    body

proc main() =
  let
    a = 10
    b = 3

  modular(12):
    let u = a + b
  echo a + b # Unfortunately this is also rewritten

  echo u
  echo addmod(a,b,12)
  echo u == addmod(a, b, 12)

main()

mratsim added a commit to mratsim/laser that referenced this issue Oct 20, 2018
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

1 participant