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

Macros? #42

Open
fcard opened this issue Nov 16, 2017 · 4 comments
Open

Macros? #42

fcard opened this issue Nov 16, 2017 · 4 comments

Comments

@fcard
Copy link
Collaborator

fcard commented Nov 16, 2017

An AST based compiler allows lisp-like macros to be implemented.

It would be very handy in implementing the remaining and future powscript extensions, as well as dealing with the fact that eval doesn't work with powscript code by introducing alternatives.

yay/nay?

@fcard fcard mentioned this issue Nov 18, 2017
77 tasks
@coderofsalvation
Copy link
Owner

yay!
macros rock.

@fcard
Copy link
Collaborator Author

fcard commented Nov 24, 2017

How about this syntax?

GENSYM_COUNT=0
macro gensym(var) # create an unique name
  GENSYM_COUNT+=1
  local name<-create-ast name "__gensym_name_$GENSYM_COUNT"
  return value :{local ~var=~name}

macro swap(x y) # swap the values of the given variables
  gensym tmp
  return code
    ~tmp=~x
    ~x=~y
    ~y=~tmp

a=1
b=2
swap a b
echo $a $b #> 2 1

Suggestions/criticism as always are welcome.


Explanation:

First off, macros manipulate data, not strings, so in order to avoid having users have to do all the things I did with setvar and noshadow in the compiler, I've come up with some syntactic sugar for returning and putting data in variables.

add(a b)
  return value $(math a+b)

x<-add 1 2
echo $x #> 3

Which would translate to Bash as something like:

add() {
  local a="${1}" b="${2}"
  printf -v "$__return_value_add" '%s' $((${a}+${b}))
}

__return_value_add=__return_value_0 add 1 2 
x=$__return_value_0
echo $x

The second bit of syntax is the code literal, :{some ~code}, which creates and returns an AST. ~ is what I used for interpolation/substitution. (e.g. v=:{10}; x=:{echo ~v} is equivalent to x=:{echo 10})

code=:{local x=~value} would be equivalent to:

ast:make code local ''
ast:make __ast_child_0 assign 'x' $value
ast:push-child $code $__ast_child_0

return code is a way to make returning multi-line ASTs simpler and more powscripty, otherwise it would need to be something like:

return value :{
  block
    ~tmp=~x
    ~x=~y
    ~y=~tmp
}

The rest I imagine is straight forward:

macro m(a b c)
  ...

creates a macro m that takes a, b, and c as arguments, which behaves like a function, except it's executed in the compilation process as it's found.


Just to give some perspective on why manipulating data is better with printf -v than with echo:

add_echo() {
  echo $((${1} + ${2}))
}
$ time for i in {1..50000}; do x=$(add_echo 1 2); done

real	0m58.490s
user	0m34.875s
sys	0m25.199s
$  time for i in {1..50000}; do __return_value_add=__return_value_0 add 1 2; x=$__return_value_0; done

real	0m1.157s
user	0m1.156s
sys	0m0.000s

So having syntax for this strategy of data passing would be nice in general.

@fcard
Copy link
Collaborator Author

fcard commented Nov 25, 2017

Alternatively instead of another type of assignment

x<-f x y

we could have a "value substitution" syntax

x=$[f x y]

Which has a number of advantages like allowing more than one to be passed to a command and being more "shell-like", but I wonder if it wouldn't be confusing.

If this requires more discussion I will open another issue, although macros require either functionality to be easy to use.

@coderofsalvation
Copy link
Owner

coderofsalvation commented Aug 28, 2018

last time I've used macros was with C (long time ago).
I like your last 'value substitution'-example, it definately looks 'shell-like'.
If this can speed up shellscripts, and it looks 'shell-ish': Im all for it.

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

No branches or pull requests

2 participants