Download
146 lines 5.3 KiBNomsuModified 2019-03-27 raw
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147
#!/usr/bin/env nomsu -V7.0.0
###
    This file contains code for defining ways to upgrade code between different versions
    of Nomsu.
    
use "filesystem"

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

$UPGRADES = {}
$ACTION_UPGRADES = ({} with fallback $ -> {})
external:
    (upgrade to $version via $upgrade_fn) means:
        $UPGRADES.$version = $upgrade_fn
    
    (upgrade action $stub to $version via $upgrade_fn) means:
        $ACTION_UPGRADES.$version.$stub = $upgrade_fn
    
    (upgrade $tree to $version as $body) parses as
        upgrade to $version via ($ -> ($, with ($tree -> $body)))
    
    (upgrade action $actions to $version as $body) compiles to:
        if ($actions is "Action" syntax tree):
            $actions = \[\$actions]
        $lua = (Lua "")
        for $action in $actions:
            $replacements = {}
            for $i in (1 to #$action):
                if ($action.$i is "Var" syntax tree):
                    $replacements.($action.$i.1) = "\(\$tree as lua id)[\$i]"
            
            define mangler
            (make tree $t) means:
                when:
                    ($t is "Var" syntax tree):
                        if $replacements.($t.1):
                            return $replacements.($t.1)
                        ..else:
                            external ($needs_mangle = (yes))
                            return ("
                                SyntaxTree{type=\(quote $t.type), source=\(quote "\($t.source)"), \(quote (mangle $t.1))}
                            ")
                    
                    ($t is syntax tree):
                        $args = []
                        for ($k = $v) in $t:
                            if ((type of $k) == "a Number"):
                                $args, add (make tree $v)
                            ..else:
                                $args, add "\($k)=\(make tree $v)"
                        
                        return "SyntaxTree{\($args, joined with ", ")}"
                    
                    else:
                        return (quote $t)
            
            unless ("\$lua" == ""):
                $lua, add "\n"
            
            $retval = (make tree $body)
            $lua, add
                Lua ("
                    upgrade_action_1_to_2_via(\(quote $action.stub), \($version as lua expr), function(\
                    ..\(\$tree as lua id))
                        return \$retval
                    end)
                ")
        
        return $lua
    
    [
        $tree upgraded from $start_version to $end_version
        $tree upgraded to $end_version from $start_version
    ] all mean:
        unless ($tree is syntax tree): return $tree
        ($ver as version list) means:
            if ($ver is "Text"):
                return (($ as number) for $ in $ver matching "[0-9]+")
            return $ver
        
        (Ver $) means:
            if ($ is "a List"):
                if ($.1 is "Text"):
                    return {.lib = $.1, .version = ($, from 2)}
                return {.version = $}
            [$lib, $ver] = ($, match "(.*)/([0-9.]+)")
            if $lib:
                return {.lib = $lib, .version = ($ver as version list)}
            return {.version = ($ as version list)}
        
        $start = (Ver $start_version)
        $end = (Ver $end_version)
        $end.lib or= $start.lib
        assume $start.lib == $end.lib
        $seen = {}
        $versions = {}
        for ($v = $) in $UPGRADES:
            $versions.$v = (yes)
        
        for ($v = $) in $ACTION_UPGRADES:
            $versions.$v = (yes)
        
        $versions = [:
            for ($v = $) in $versions:
                $v2 = (Ver $v)
                if ($v2.lib == $start.lib):
                    if ($start.version < $v2.version <= $end.version): add $v
        ]
        
        sort $versions by $ -> ($ as version list)
        $curr_version = $start_version
        for $ver in $versions:
            $tree =
                SyntaxTree
                    {: for ($k = $v) in $tree: add $k = ($v upgraded from $curr_version to $ver)}
            
            if (($tree.type == "Action") and $ACTION_UPGRADES.$ver):
                $(upgrade 1) = $ACTION_UPGRADES.$ver.($tree, get stub)
                if $(upgrade 1):
                    $tree = (upgrade $tree)
                    go to (next version)
            
            if $UPGRADES.$ver:
                $tree = ($UPGRADES.$ver $tree $ver)
                go to (next version)
            
            --- (next version) ---
            $curr_version = $ver
        
        if ($tree.version != $end_version):
            $tree = (SyntaxTree {: for ($k = $v) in $tree: add $k = $v})
            $tree.version = $end_version
            if $tree.shebang:
                unless ($end_version is "Text"):
                    $end_version = ($end_version, joined with ".")
                $tree.shebang = "#!/usr/bin/env nomsu -V\$end_version\n"
        
        return $tree
    
    ($tree upgraded from $start_version) means
        $tree upgraded from $start_version to $(NOMSU VERSION)
    
    ($tree upgraded to $end_version) means
        $tree upgraded from ($tree.version or $(NOMSU VERSION)) to $end_version
    
    ($tree upgraded) means
        $tree upgraded from ($tree.version or $(NOMSU VERSION)) to $(NOMSU VERSION)