Code Monkey home page Code Monkey logo

uuagc's People

Contributors

a-middelk avatar atzedijkstra avatar doaitse avatar fptje avatar jbransen avatar noughtmare avatar serras avatar

Stargazers

 avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

uuagc's Issues

Template Haskell

I have tought a bit about using template haskell with uuagc.

Initial working version

First we could use a file quasi quoter (made with the quoteFile function) to load and compile an ag file.

Options can be passed to this quasi quoter by defining a specific variable (say agOptions) as, for example, a certain string constant. This variable can be looked up by the quasi quoter and the string constant can be read.

Edit: an annoyance is that due to the stage restriction you cannot lookup variables that are declared in the module itself, so you need to put this configuration variable in a separate module.

Edit2: Maybe we can avoid the stage restriction by using addModFinalizer in combination with addTopDecls. I wonder if those work together.

Edit3: No, lookupValueName works in addModFinalizer, but reify doesn't. Instead maybe we could just read a file with an IO action, maybe even the module itself (we can get the file name with loc_filename <$> location) and store the options in a comment?

Edit4: We can work around the whole problem by using plain TH functions instead of quasi quoters:

-- TH.hs
module TH where

import Language.Haskell.TH

useOption :: String -> Q [Dec]
useOption x = return [ValD (VarP (mkName "result")) (NormalB (LitE (StringL x))) []]
-- Main.hs
{-# LANGUAGE TemplateHaskell #-}

import TH

useOption "semfuns"

main :: IO ()
main = print result

What is also required is a way to convert an execution plan to template haskell.
It should be pretty straightforward, copy over ExecutionPlan2Hs.ag to ExecutionPlan2TH.ag and rewrite all the functions to generate template haskell declarations.

Edit: I just noticed that there is ExecutionPlan2Hs.ag and PrintCode.ag which both function as the final step to Haskell code. The execution plan is used when loag or kennedy warren is enabled, and the code is used otherwise. I started with rewriting the execution plan printer, but now I realize I should probably start with the code printer.

A difficult part will probably be the conversion of embedded haskell snippets to template haskell data types. The haskell-src-meta package is probably our best bet.

The suggested plan up to this point seems to me like it should be enough to build single file grammars, but I don't think it will be able to handle grammars that include other grammars.

A more modular solution

To go even further we could investigate using the Haskell module system instead of the ad-hoc #include system to make the attribute grammars more modular (and possibly allow importing attribute grammars across Haskell packages.

The idea is to save generated attribute grammar information in special deterministically named variables that are unique for each module and uuagc version perhaps. Any quasi quoter can lookup this variable which could simply store all necessary information in one big string literal, but perhaps we can do better.

To get such unique names we could use a hashing function of the module name and uuagc name and version. That can then be base64 encoded with the characters A-Z, a-z, 0-9, and _ and ' which are legal characters in variable names. Using a good hash function should ensure that no person can accidentally use the same variable name while still ensuring that this name can be generated by quasi quoters in other modules.

Question: how to make sure that that unique variable is always exported? Answer: We could make a special template haskell splice that takes a list of imports as input and adds the special variable to that list. It is not possible to generate an export list (or even an import list) with Template Haskell.

This is actually a pretty important point. We can just write these imports in the Haskell module that contains the template haskell expression to generate the attribute grammar code. But if we want to import semantic functions from other modules then we need to make sure that all the Haskell code in those semantic modules has the right imports. A solution might be to bind each Haskell code block to a Haskell variable which uses imports from the module that it is defined in. Those variables can then be exported and imported in other modules and the names can be transferred via the type literal trick as described in the comment below. I think we can require users to use implicit exports so that everything is automatically exported.

Extras

If this system if successfully implemented then it might also make sense to implement template haskell functions that can automatically derive attribute grammar nonterminals from existing data types. That would make it much easier to integrate attribute grammars into existing projects.

Update: I just found out that this would be similar to the Haskell2AG tool that is in the tools directory.


Edit: The whole passing of information through constant variables cannot be done, see the note here:

The Maybe Dec field contains Just the declaration which defined the variable - including the RHS of the declaration - or else Nothing, in the case where the RHS is unavailable to the compiler. At present, this value is always Nothing: returning the RHS has not yet been implemented because of lack of interest.

That means we cannot access the constant value even if we know the name.

Maybe an easy workaround is to use type-level string literals and store the information in the types instead of in the RHS.

UUAGC cabal plugin fails with source-repository-package

To reproduce:

  1. make a fresh cabal package
  2. add llvm-pretty-referential to the build-depends
  3. make a cabal-project file with these contents:
packages: .

source-repository-package
    type: git
    location: https://github.com/noughtmare/llvm-pretty-referential.git
    tag: b927f1a81e90920dedbdd1d3645164a39473eb3d
  1. Run cabal build

This results in:

[UUAGC] processing: src/Text/LLVM/AG.ag generating: dist/build/Text/LLVM/AG.hs
Warning: No options found for src/Text/LLVM/AG.ag
src/Text/LLVM/AG.ag:5:1: error: parser expecting EXTENDS or INCLUDE or a statement or end of file

It seems like the uuagc_options file is not being picked up when building the package in this way.

The update-src-generated.sh is outdated

It doesn't work anymore with the new cabal commands. The generated files are no longer stored in dist/build/. And, now, the LINE pragmas include the full file path which is not portable.

Maybe cabal has some options to get the relative file path back and to find the location of the generated .hs files.

EDIT: I actually think the old paths in half of the LINE pragmas were wrong anyway, so maybe those lines should just be filtered out or maybe they shouldn't be generated in the first place?

EDIT: So, half of the pragmas are not wrong (but they do point to the old location from before the files were moved into src-generated). They point back to the current file for errors that happen in portions of the code that were not based on lines in the original .ag file. We could rewrite these paths with a simple regex. Something like this should work:

$ find src-generated -type f -name "*.hs" -exec sed -i \
   's/^{-# LINE \([0-9]\+\) ".*\/build\/\(.*\.hs\)" #-}$/{-# LINE \1 "src-generated\/\2" #-}/' {} \;

uuagc-cabal 1.0.6.0 fails under GHC 8.4

    [4 of 5] Compiling Distribution.Simple.UUAGC.UUAGC ( src/Distribution/Simple/UUAGC/UUAGC.hs, .stack-work/dist/i386-linux/Cabal-2.2.0.1/build/Distribution/Simple/UUAGC/UUAGC.o )

    /tmp/stack4729/uuagc-cabal-1.0.6.0/src/Distribution/Simple/UUAGC/UUAGC.hs:105:51: error:
        • Couldn't match type ‘PreProcessor’
                         with ‘ComponentLocalBuildInfo -> PreProcessor’
          Expected type: [PPSuffixHandler]
            Actual type: [([Char],
                           BuildInfo -> LocalBuildInfo -> PreProcessor)]
        • In the ‘hookedPreProcessors’ field of a record
          In the expression:
            simpleUserHooks
              {hookedPreProcessors = ("ag", ag)
                                       : ("lag", ag) : knownSuffixHandlers,
               buildHook = uuagcBuildHook uuagc, sDistHook = uuagcSDistHook uuagc}
          In an equation for ‘hooks’:
              hooks
                = simpleUserHooks
                    {hookedPreProcessors = ("ag", ag)
                                             : ("lag", ag) : knownSuffixHandlers,
                     buildHook = uuagcBuildHook uuagc, sDistHook = uuagcSDistHook uuagc}

Installing uuagc (0.9.52.2) via cabal new-install fails

This may be a bug in Cabal instead of in uuagc, but you'll know that better than I do. :)

When installing uuagc using the new-style commands, i.e. cabal new-install uuagc, the dependency resolution phase fails due to a conflicting dependency on Cabal. Somehow, it determines that uuagc, directly or indirectly, depends on both Cabal >= 2.5 and <1.25, which clearly is not going to work.

Installing with the command cabal new-install uuagc --constraint='uuagc==0.9.52.2' --verbose=3 (where the constraint is added to prevent cabal from trying older versions of uuagc), the following dependency resolution logs are generated: uuagc-conflicts.txt

From some cursory looking around, I have not been able to find the directive that requires Cabal to have a version <1.25, but that is probably my unfamiliarity with the dependency tree.

Thanks!

System info:

  • macOS 10.13.6, though this also fails on Arch Linux
  • cabal-install version 2.4.1.0
  • ghc version 8.6.4

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.