Skip to content

Commit

Permalink
Merge pull request #86 from melt-umn/feature/env
Browse files Browse the repository at this point in the history
Refactoring to environment
  • Loading branch information
krame505 authored Feb 9, 2018
2 parents afc9b29 + e599ee4 commit 2c73532
Show file tree
Hide file tree
Showing 30 changed files with 297 additions and 253 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ imports edu:umn:cs:melt:ableC:abstractsyntax:env;

-- The environment used at the top-level.
global initialEnv :: Decorated Env =
openScope(
openScopeEnv(
addEnv(getInitialEnvDefs(),
emptyEnv()));

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,46 +42,7 @@ parser exprParser :: cst:Expr_c {
}

-- Wrapper functions to call parsers and return asts
function parseDecls
Decls ::= text::String
{
local result::ParseResult<cst:TranslationUnit_c> =
declsParser(text, s"parseDecls(\"\"\"\n${foldLineNums(text)}\n\"\"\")");
return
if result.parseSuccess
then foldDecl(result.parseTree.ast)
else error("Syntax errors in parseDecls string:\n" ++ result.parseErrors);
}

function parseDecl
Decl ::= text::String
{
local result::ParseResult<cst:ExternalDeclaration_c> =
declParser(text, s"parseDecl(\"\"\"\n${foldLineNums(text)}\n\"\"\")");
return
if result.parseSuccess
then result.parseTree.ast
else error("Syntax errors in parseDecl string:\n" ++ result.parseErrors);
}

function parseStmt
Stmt ::= text::String
{
local result::ParseResult<cst:BlockItemList_c> =
stmtParser(text, s"parseStmt(\"\"\"\n${foldLineNums(text)}\n\"\"\")");
return
if result.parseSuccess
then foldStmt(result.parseTree.ast)
else error("Syntax errors in parseStmt string:\n" ++ result.parseErrors);
}

function parseExpr
Expr ::= text::String
{
local result::ParseResult<cst:Expr_c> =
exprParser(text, s"parseExpr(\"\"\"\n${foldLineNums(text)}\n\"\"\")");
return
if result.parseSuccess
then result.parseTree.ast
else error("Syntax errors in parseExpr string:\n" ++ result.parseErrors);
}
global parseDecls::(Decls ::= String) = \ text::String -> foldDecl(parseInline("Decls", declsParser, text).ast);
global parseDecl::(Decl ::= String) = \ text::String -> parseInline("Decl", declParser, text).ast;
global parseStmt::(Stmt ::= String) = \ text::String -> foldStmt(parseInline("Stmt", stmtParser, text).ast);
global parseExpr::(Expr ::= String) = \ text::String -> parseInline("Expr", exprParser, text).ast;
Original file line number Diff line number Diff line change
@@ -1,5 +1,16 @@
grammar edu:umn:cs:melt:ableC:abstractsyntax:construction:parsing;

function parseInline
a ::= nt::String parser::(ParseResult<a> ::= String String) text::String
{
local result::ParseResult<a> =
parser(text, s"parse${nt}(\"\"\"\n${foldLineNums(text)}\n\"\"\")");
return
if result.parseSuccess
then result.parseTree
else error("Syntax errors in parse${nt} string:\n" ++ result.parseErrors);
}

-- TODO: Maybe these belong in core or langutil?
function padRight
String ::= len::Integer s::String
Expand All @@ -16,4 +27,4 @@ String ::= text::String
local lineNums::[Integer] = 1 :: map(\i::Integer -> i + 1, lineNums); -- Lazyness is awesome.
local lines::[String] = explode("\n", text);
return implode("\n", zipWith(\lineNum::Integer line::String -> padRight(3, toString(lineNum)) ++ line, lineNums, lines));
}
}
1 change: 0 additions & 1 deletion edu.umn.cs.melt.ableC/abstractsyntax/env/Def.sv
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
grammar edu:umn:cs:melt:ableC:abstractsyntax:env;


abstract production labelDef
top::Def ::= s::String l::LabelItem
{
Expand Down
42 changes: 17 additions & 25 deletions edu.umn.cs.melt.ableC/abstractsyntax/env/Env.sv
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
grammar edu:umn:cs:melt:ableC:abstractsyntax:env;

imports edu:umn:cs:melt:ableC:abstractsyntax:host;
imports silver:util:raw:treemap as tm;

{--
- The environment values that get passed around and used to look up names.
Expand Down Expand Up @@ -34,9 +33,10 @@ closed nonterminal Def
synthesized attribute defs :: [Def] with ++;
{--
- For Function-Scope definitions (e.g. Labels in functions)
- @see defs for normal definitions
- Note that since the env may determine the forward, and functionDefs on a production determine the env provided to that
- production, functionDefs must be computed without using the forward.
-}
synthesized attribute functiondefs :: [Def] with ++;
synthesized attribute functionDefs :: [Def] with ++;
{--
- For local-scope only definitions (e.g. struct and union fields)
- Used in conjunction with 'tagEnv'.
Expand All @@ -46,7 +46,7 @@ synthesized attribute functiondefs :: [Def] with ++;
-
- @see defs for normal definitions
-}
synthesized attribute localdefs :: [Def] with ++;
synthesized attribute localDefs :: [Def] with ++;
{--
- The environment, on which all lookups are performed.
-}
Expand All @@ -56,14 +56,18 @@ autocopy attribute env :: Decorated Env;
-}
synthesized attribute tagEnv :: Decorated Env;


-- Environment manipulation functions

function emptyEnv
Decorated Env ::=
{
return decorate emptyEnv_i() with {};
}
function openScopeEnv
Decorated Env ::= e::Decorated Env
{
return decorate openScopeEnv_i(e) with {};
}
function addEnv
Decorated Env ::= d::[Def] e::Decorated Env
{
Expand All @@ -74,11 +78,6 @@ Decorated Env ::= d::Defs e::Decorated Env
{
return decorate addEnv_i(d, e) with {};
}
function openScope
Decorated Env ::= e::Decorated Env
{
return decorate openScope_i(e) with {};
}
function globalEnv
Decorated Env ::= e::Decorated Env
{
Expand All @@ -90,50 +89,43 @@ Decorated Env ::= e::Decorated Env
function lookupValue
[ValueItem] ::= n::String e::Decorated Env
{
return readScope_i(n, e.values);
return lookupScope(n, e.values);
}
function lookupTag
[TagItem] ::= n::String e::Decorated Env
{
return readScope_i(n, e.tags);
return lookupScope(n, e.tags);
}
function lookupLabel
[LabelItem] ::= n::String e::Decorated Env
{
return readScope_i(n, e.labels);
return lookupScope(n, e.labels);
}
function lookupRefId
[RefIdItem] ::= n::String e::Decorated Env
{
return readScope_i(n, e.refIds);
return lookupScope(n, e.refIds);
}

function lookupMisc
[MiscItem] ::= n::String e::Decorated Env
{
return readScope_i(n, e.misc);
return lookupScope(n, e.misc);
}


function lookupValueInLocalScope
[ValueItem] ::= n::String e::Decorated Env
{
return tm:lookup(n, head(e.values));
return lookupInLocalScope(n, e.values);
}
function lookupTagInLocalScope
[TagItem] ::= n::String e::Decorated Env
{
return tm:lookup(n, head(e.tags));
}
function lookupLabelInLocalScope
[LabelItem] ::= n::String e::Decorated Env
{
return tm:lookup(n, head(e.labels));
return lookupInLocalScope(n, e.tags);
}

function lookupMiscInLocalScope
[MiscItem] ::= n::String e::Decorated Env
{
return tm:lookup(n, head(e.misc));
return lookupInLocalScope(n, e.misc);
}

92 changes: 30 additions & 62 deletions edu.umn.cs.melt.ableC/abstractsyntax/env/EnvPlumbing.sv
Original file line number Diff line number Diff line change
@@ -1,22 +1,17 @@
grammar edu:umn:cs:melt:ableC:abstractsyntax:env;

{-
- The enivronment in ableC is represented as a nonterminal which is used to build up various lists
- of 'scopes'. Each scope is a treemap that is used to look up a value. If the value is not
- found in the current scope, then the next one is tried, etc. The last scope represents the
- global level. This is to allow names in the environment to be shadowed by a name in a lower
- scope, while still preventing a name from being declared twice in the local scope.
- Contribs is just a list of items to add to a scope.
- The enivronment in ableC is represented as a nonterminal 'Env' which is used to build up various
- scopes, reperesenting the contents of each namespace.
- Contributions to an environment are represented as another nonterminal 'Defs', which is used to
- build up contributions to each individual scope in an Env.
-}

type Scope<a> = [tm:Map<String a>];
type Contribs<a> = [Pair<String a>];

synthesized attribute labels :: Scope<LabelItem>;
synthesized attribute tags :: Scope<TagItem>;
synthesized attribute values :: Scope<ValueItem>;
synthesized attribute refIds :: Scope<RefIdItem>;
synthesized attribute misc :: Scope<MiscItem>;
synthesized attribute labels :: Scopes<LabelItem>;
synthesized attribute tags :: Scopes<TagItem>;
synthesized attribute values :: Scopes<ValueItem>;
synthesized attribute refIds :: Scopes<RefIdItem>;
synthesized attribute misc :: Scopes<MiscItem>;
synthesized attribute globalEnv :: Decorated Env;

synthesized attribute labelContribs :: Contribs<LabelItem>;
Expand All @@ -26,33 +21,6 @@ synthesized attribute refIdContribs :: Contribs<RefIdItem>;
synthesized attribute miscContribs :: Contribs<MiscItem>;
synthesized attribute globalDefs :: [Def];

{-- Adds contributions to the innermost scope -}
function augmentScope_i
Scope<a> ::= d::Contribs<a> s::Scope<a>
{
return tm:add(d, head(s)) :: tail(s);
}
{-- Adds contributions to the outermost scope -}
function augmentGlobalScope_i
Scope<a> ::= d::Contribs<a> s::Scope<a>
{
return case d, s of
| [], _ -> s
| _, [_] -> augmentScope_i(d, s)
| _, h :: t -> h :: augmentGlobalScope_i(d, t)
end;
}
{-- Looks up an identifier in the closest scope that has a match -}
function readScope_i
[a] ::= name::String scope::Scope<a>
{
-- Laziness is awesome.
return case dropWhile(null, map(tm:lookup(name, _), scope)) of
| h :: _ -> h
| [] -> []
end;
}

{- Environment representation productions provide implementations for env functions
- emptyEnv_i creates the basic environment with empty global scopes
- addEnv_i adds provided defs to the current (first on list) scope, and global defs to the global (last on list) scope
Expand All @@ -63,40 +31,40 @@ function readScope_i
abstract production emptyEnv_i
top::Env ::=
{
top.labels = [tm:empty(compareString)];
top.tags = [tm:empty(compareString)];
top.values = [tm:empty(compareString)];
top.refIds = [tm:empty(compareString)];
top.misc = [tm:empty(compareString)];
top.labels = emptyScope();
top.tags = emptyScope();
top.values = emptyScope();
top.refIds = emptyScope();
top.misc = emptyScope();
}
abstract production addEnv_i
top::Env ::= d::Defs e::Decorated Env
{
production gd::Defs = foldr(consDefs, nilDefs(), d.globalDefs);

top.labels = augmentGlobalScope_i(gd.labelContribs, augmentScope_i(d.labelContribs, e.labels));
top.tags = augmentGlobalScope_i(gd.tagContribs, augmentScope_i(d.tagContribs, e.tags));
top.values = augmentGlobalScope_i(gd.valueContribs, augmentScope_i(d.valueContribs, e.values));
top.refIds = augmentGlobalScope_i(gd.refIdContribs, augmentScope_i(d.refIdContribs, e.refIds));
top.misc = augmentGlobalScope_i(gd.miscContribs, augmentScope_i(d.miscContribs, e.misc));
top.labels = addGlobalScope(gd.labelContribs, addScope(d.labelContribs, e.labels));
top.tags = addGlobalScope(gd.tagContribs, addScope(d.tagContribs, e.tags));
top.values = addGlobalScope(gd.valueContribs, addScope(d.valueContribs, e.values));
top.refIds = addGlobalScope(gd.refIdContribs, addScope(d.refIdContribs, e.refIds));
top.misc = addGlobalScope(gd.miscContribs, addScope(d.miscContribs, e.misc));
}
abstract production openScope_i
abstract production openScopeEnv_i
top::Env ::= e::Decorated Env
{
top.labels = tm:empty(compareString) :: e.labels;
top.tags = tm:empty(compareString) :: e.tags;
top.values = tm:empty(compareString) :: e.values;
top.refIds = tm:empty(compareString) :: e.refIds;
top.misc = tm:empty(compareString) :: e.misc;
top.labels = openScope(e.labels);
top.tags = openScope(e.tags);
top.values = openScope(e.values);
top.refIds = openScope(e.refIds);
top.misc = openScope(e.misc);
}
abstract production globalEnv_i
top::Env ::= e::Decorated Env
{
top.labels = [last(e.labels)];
top.tags = [last(e.tags)];
top.values = [last(e.values)];
top.refIds = [last(e.refIds)];
top.misc = [last(e.misc)];
top.labels = globalScope(e.labels);
top.tags = globalScope(e.tags);
top.values = globalScope(e.values);
top.refIds = globalScope(e.refIds);
top.misc = globalScope(e.misc);
}

{- Definition list productions provide a way of folding up defs into Contribs lists
Expand Down
12 changes: 7 additions & 5 deletions edu.umn.cs.melt.ableC/abstractsyntax/env/LabelItem.sv
Original file line number Diff line number Diff line change
@@ -1,17 +1,19 @@
grammar edu:umn:cs:melt:ableC:abstractsyntax:env;

nonterminal LabelItem;

-- TODO: Should consider whether we want to change the Stmt abstract syntax
-- to have a LabelStmt, so we can be more specific here
nonterminal LabelItem with sourceLocation;

-- Note that we unfortunately can't include a reference to the labeled statement here, since these
-- are function-scope defs, which need to be computed without the use of env to avoid a circular
-- dependancy.
abstract production labelItem
top::LabelItem ::= s::Decorated Stmt
top::LabelItem ::= sourceLocation::Location
{
top.sourceLocation = sourceLocation;
}

abstract production errorLabelItem
top::LabelItem ::=
{
top.sourceLocation = loc("nowhere", -1, -1, -1, -1, -1, -1);
}

2 changes: 1 addition & 1 deletion edu.umn.cs.melt.ableC/abstractsyntax/env/MiscItem.sv
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
grammar edu:umn:cs:melt:ableC:abstractsyntax:env;

nonterminal MiscItem;
closed nonterminal MiscItem;

{- Misc items are used to put various bits of information into the
environment such that it can be extracted later by, typically, some
Expand Down
2 changes: 1 addition & 1 deletion edu.umn.cs.melt.ableC/abstractsyntax/env/RefIdItem.sv
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ grammar edu:umn:cs:melt:ableC:abstractsyntax:env;
-
- This unfortunately complicates the types a bit, since
-}
nonterminal RefIdItem with moduleName, tagEnv;
closed nonterminal RefIdItem with moduleName, tagEnv;

{-- Name resolves to a full struct declaration -}
abstract production structRefIdItem
Expand Down
Loading

0 comments on commit 2c73532

Please sign in to comment.