Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 13 additions & 2 deletions skiplang/compiler/src/SkipParser.sk
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ mutable class SkipParser{
lazy: Bool,
tokenLexer: mutable SkipLexer.SkipCoreLexer,
templateLexer: mutable SkipLexer.TemplateLexer,
accessedEnvVars: mutable Set<String> = mutable Set[],
} extends Parser.Parser {
static fun create(source: String, lazy: Bool): mutable this {
lexingPosition = Lexer.LexingPosition::create(source);
Expand All @@ -54,6 +55,10 @@ mutable class SkipParser{
};
}

readonly fun getAccessedEnvVars(): SortedSet<String> {
SortedSet::createFromIterator(this.accessedEnvVars.values())
}

mutable fun createPeekParser(): mutable this {
mutable static{
lazy => this.lazy,
Expand Down Expand Up @@ -4791,6 +4796,8 @@ mutable class SkipParser{
};
closeParen = this.eatTree(TokenKind.CLOSE_PAREN());

this.accessedEnvVars.insert(varName.getToken().stringLiteralValue());

ParseTree.EnvMacroTree{
range => this.createRange(start),
envKeyword,
Expand Down Expand Up @@ -5108,7 +5115,7 @@ fun parseSource(
source: String,
isLazy: Bool,
filename: String = "",
): Parser.ParseResults {
): (Parser.ParseResults, SortedSet<String>) {
parser = SkipParser::create(source, isLazy);
tree = parser.parseSourceUnit();
allErrors = parser.getErrors();
Expand All @@ -5124,7 +5131,11 @@ fun parseSource(
if (errors.isEmpty() && !isLazy) {
Parser.validateParse(tokens, tree, filename);
};
Parser.ParseResults{tokens, comments => parser.getComments(), tree, errors};

(
Parser.ParseResults{tokens, comments => parser.getComments(), tree, errors},
parser.getAccessedEnvVars(),
)
}

fun getNamedParameterDefaultValue(tree: ParseTree): ParseTree {
Expand Down
41 changes: 15 additions & 26 deletions skiplang/compiler/src/compile.sk
Original file line number Diff line number Diff line change
Expand Up @@ -245,28 +245,7 @@ fun getOrInitializeBackend(context: mutable SKStore.Context): SKStore.EagerDir {
};

if (conf.emit == "sklib") {
accessed_env_vars = context.getGlobal(
FileCache.kEnvAccessGlobal,
) match {
| None() -> SortedSet[]
| Some(envMapFile) ->
FileCache.EnvMapFile::type(envMapFile)
.value.maybeGet(conf.lib_name)
.default(SortedSet[])
};
env_dir = SKStore.EHandle(
SKStore.SID::keyType,
SKStore.StringFile::type,
SKStore.DirName::create(
`/packageEnv/${conf.lib_name.default("_default")}/`,
),
);
env = SortedMap::createFromIterator(
accessed_env_vars
.map(v -> (v, env_dir.unsafeGet(context, SKStore.SID(v)).value))
.iterator(),
);
compile_sklib(conf, env);
compile_sklib(context, conf);
return void
};

Expand Down Expand Up @@ -423,11 +402,21 @@ fun compile_binary(
})
}

fun compile_sklib(
conf: Config.Config,
env_vars: SortedMap<String, String>,
): void {
fun compile_sklib(context: mutable SKStore.Context, conf: Config.Config): void {
runCompilerPhase("native/write_sklib", () -> {
accessed_env_vars = SortedSet::createFromItems(
FileCache.packageEnvAccessDir.getArray(
context,
SKStore.SID(conf.lib_name.fromSome()),
).map(v -> v.value),
);
env_dir = FileCache.packageEnvDir(conf.lib_name);
env_vars = SortedMap::createFromIterator(
accessed_env_vars
.map(v -> (v, env_dir.unsafeGet(context, SKStore.SID(v)).value))
.iterator(),
);

// NOTE: Static libraries (`.a` archives) provided as input files are
// bundled into the `sklib`.
sklib = mutable SklibBuilder(
Expand Down
1 change: 0 additions & 1 deletion skiplang/compiler/src/convertTree.sk
Original file line number Diff line number Diff line change
Expand Up @@ -884,7 +884,6 @@ class Converter{file: FileCache.InputSource} {
fun convertEnvMacro(_range: FileRange, varName: ParseTree): SkipAst.Expr_ {
SkipAst.EnvMacro(
this.createName(varName, varName.getToken().stringLiteralValue()),
this.file.pkg_opt,
)
}

Expand Down
2 changes: 1 addition & 1 deletion skiplang/compiler/src/skfmt.sk
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ fun prettyPrint(
contents: String,
filename: String,
): Result<String, SkipError.Error> {
parsed = SkipParser.parseSource(contents, false);
(parsed, _) = SkipParser.parseSource(contents, false);
if (parsed.errors.size() > 0) {
// Parse errors are expected. Exceptions are bugs.
Failure(
Expand Down
2 changes: 1 addition & 1 deletion skiplang/compiler/src/skipAst.sk
Original file line number Diff line number Diff line change
Expand Up @@ -365,7 +365,7 @@ base class Expr_ {
functionName: ?Name,
body: Expr,
)
| EnvMacro(Name, ?String)
| EnvMacro(Name)
| MacroDot(Expr, Name)
| MacroStaticDot(Expr, Name)
}
Expand Down
2 changes: 1 addition & 1 deletion skiplang/compiler/src/skipAstPp.sk
Original file line number Diff line number Diff line change
Expand Up @@ -861,7 +861,7 @@ fun expr(o: mutable BufferedPrinter.Out, e: SkipAst.Expr): void {
};
o.out(") ");
expr(o, body)
| SkipAst.EnvMacro(varName, _) ->
| SkipAst.EnvMacro(varName) ->
o.out("#env (");
o.out(literal_to_string(SkipAst.StringLiteral(varName.i1)));
o.out(")")
Expand Down
29 changes: 1 addition & 28 deletions skiplang/compiler/src/skipExpand.sk
Original file line number Diff line number Diff line change
Expand Up @@ -3419,34 +3419,7 @@ fun expr_(
functionName,
expr(context, env, body),
)
| A.EnvMacro(varName, pkg_opt) ->
pkg_env = SKStore.EHandle(
SKStore.SID::keyType,
SKStore.StringFile::type,
// FIXME: Ensure package names cannot start with an underscore to avoid clash with `_default`.
SKStore.DirName::create(`/packageEnv/${pkg_opt.default("_default")}/`),
);
name = varName.i1;
value = pkg_env.maybeGet(context, SKStore.SID(name)) match {
| None() ->
SkipError.error(varName.i0, `Environment variable ${name} is not set.`)
| Some(v) -> v.value
};
// Record access to env variable.
cur_env_map = context.getGlobal(FileCache.kEnvAccessGlobal) match {
| None() -> SortedMap[]
| Some(envMapFile) -> FileCache.EnvMapFile::type(envMapFile).value
};
context.setGlobal(
FileCache.kEnvAccessGlobal,
FileCache.EnvMapFile(
cur_env_map.set(
pkg_opt,
cur_env_map.maybeGet(pkg_opt).default(SortedSet[]).set(name),
),
),
);
A.Literal(A.StringLiteral(value))
| A.EnvMacro(varName) -> A.EnvMacro(varName)
}
}

Expand Down
34 changes: 31 additions & 3 deletions skiplang/compiler/src/skipMain.sk
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,9 @@ fun type_program(
): SKStore.EHandle<SKStore.SID, SkipTyping.DefFile> {
parsed_program = FileCache.fileDir.map(
FileCache.InputSource::keyType,
SkipParse.DefsFile::type,
SkipParse.DefsWithAccessedEnvVarsFile::type,
context,
SkipParse.astDirName,
SKStore.DirName::create("/astAndAccessedEnvVarsCache/"),
(context, writer, key, sources) ~> {
source = sources.first;
SkipError.catchErrors(0, context, () -> {
Expand All @@ -26,7 +26,35 @@ fun type_program(
},
);

(defsDir, childDir) = SkipExpand.program(context, parsed_program);
_ = parsed_program.map(
SKStore.SID::keyType,
SKStore.StringFile::type,
context,
FileCache.packageEnvAccessDirName,
(_context, writer, key, values) ~> {
writer.setArray(
SKStore.SID(key.pkg_opt.default(FileCache.kAnonymousPackageName)),
values
.getUnique()
.fromSome()
.accessed_env_vars.values()
.map(v -> SKStore.StringFile(v))
.collect(Array),
)
},
);

ast = parsed_program.map(
FileCache.InputSource::keyType,
SkipParse.DefsFile::type,
context,
SkipParse.astDirName,
(_context, writer, key, values) ~> {
writer.set(key, SkipParse.DefsFile(values.getUnique().fromSome().defs))
},
);

(defsDir, childDir) = SkipExpand.program(context, ast);
inhDir = SkipInherit.populateClassesDir(context);
SkipNaming.populateClasses(context, defsDir, inhDir, childDir);
SkipNaming.populateFuns(context, defsDir);
Expand Down
17 changes: 14 additions & 3 deletions skiplang/compiler/src/skipNaming.sk
Original file line number Diff line number Diff line change
Expand Up @@ -3660,6 +3660,18 @@ fun expandForEachMacro(
N.Bind(iteratorn, getIterator, flagged)
}

fun expandEnvMacro(context: mutable SKStore.Context, varName: A.Name): N.Expr_ {
(pos, name) = varName;
value = FileCache.packageEnvDir(pos.file.pkg_opt).maybeGet(
context,
SKStore.SID(name),
) match {
| None() -> SkipError.error(pos, `Environment variable ${name} is not set.`)
| Some(v) -> v.value
};
N.Literal(A.StringLiteral(value))
}

fun reportDuplicateMacro(
pos: FileRange,
id: String,
Expand Down Expand Up @@ -3816,9 +3828,8 @@ fun expr_(
| A.Literal(l) -> N.Literal(l)
| A.Var(n) -> N.Var(n)
| A.MacroVar(n) -> expandExpressionMacro(env, n)
| A.Seq _
| A.EnvMacro _ ->
invariant_violation("assert false")
| A.Seq _ -> invariant_violation("assert false")
| A.EnvMacro(n) -> expandEnvMacro(context, n)
| A.If(e1, e2, e3) ->
N.If(
expr(context, acc, env, e1),
Expand Down
59 changes: 44 additions & 15 deletions skiplang/compiler/src/skipParse.sk
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,18 @@ const packageDir: SKStore.EHandle<
packageDirName,
);

const packageEnvAccessDirName: SKStore.DirName = SKStore.DirName::create(
"/packageEnvAccess/",
);
const packageEnvAccessDir: SKStore.EHandle<
SKStore.SID,
SKStore.StringFile,
> = SKStore.EHandle(
SKStore.SID::keyType,
SKStore.StringFile::type,
packageEnvAccessDirName,
);

fun pkgDelta(
old_pkg: InputPackageFiles,
new_pkg: InputPackageFiles,
Expand Down Expand Up @@ -205,17 +217,33 @@ fun writeFiles(
}
}

// FIXME: Ensure package names cannot start with an underscore to avoid clash with `_anonymous`.
const kAnonymousPackageName: String = "_anonymous";

fun packageEnvDirName(pkg_opt: ?String): SKStore.DirName {
SKStore.DirName::create(
`/packageEnv/${pkg_opt.default(kAnonymousPackageName)}/`,
)
}

fun packageEnvDir(
pkg_opt: ?String,
): SKStore.EHandle<SKStore.SID, SKStore.StringFile> {
SKStore.EHandle(
SKStore.SID::keyType,
SKStore.StringFile::type,
packageEnvDirName(pkg_opt),
)
}

fun updatePackageEnv(
context: mutable SKStore.Context,
pkg_opt: ?String,
env: Array<(String, String)>,
): void {
envDirName = SKStore.DirName::create(
`/packageEnv/${pkg_opt.default("_default")}/`,
);
envDirName = packageEnvDirName(pkg_opt);
envDir = context.unsafeMaybeGetEagerDir(envDirName) match {
| Some _ ->
SKStore.EHandle(SKStore.SID::keyType, SKStore.StringFile::type, envDirName)
| Some _ -> packageEnvDir(pkg_opt)
| None _ ->
context.mkdir(SKStore.SID::keyType, SKStore.StringFile::type, envDirName)
};
Expand All @@ -236,12 +264,6 @@ fun updatePackageEnv(
};
}

const kEnvAccessGlobal: String = "ACCESSED_ENV_MAP";

class EnvMapFile(
value: SortedMap<?String, SortedSet<String>>,
) extends SKStore.File

module end;

module SkipParse;
Expand All @@ -254,11 +276,18 @@ const astDir: SKStore.EHandle<SKStore.SID, DefsFile> = SKStore.EHandle(
);

class DefsFile(value: List<SkipAst.Definition>) extends SKStore.File
class DefsWithAccessedEnvVarsFile(
defs: List<SkipAst.Definition>,
accessed_env_vars: SortedSet<String>,
) extends SKStore.File

fun parseFile(file: FileCache.InputSource, source: String): DefsFile {
fileResult = SkipParser.parseSource(source, true);
ast = parseToAst(file, fileResult);
DefsFile(ast)
fun parseFile(
file: FileCache.InputSource,
source: String,
): DefsWithAccessedEnvVarsFile {
(fileResult, accessed_env_vars) = SkipParser.parseSource(source, true);
defs = parseToAst(file, fileResult);
DefsWithAccessedEnvVarsFile(defs, accessed_env_vars)
}

fun parseToAst(
Expand Down