Skip to content

Instantly share code, notes, and snippets.

@chronos-tachyon
Created November 22, 2020 03:22
Show Gist options
  • Save chronos-tachyon/14e7d27ddd11369a6630cecb1b30df7c to your computer and use it in GitHub Desktop.
Save chronos-tachyon/14e7d27ddd11369a6630cecb1b30df7c to your computer and use it in GitHub Desktop.
// SpiderScript compiler.
#version(1)
module spdr::compiler
import argparse
import io
import os
import runtime
import spdr::ast
import spdr::parser
import sync
type Arch = enum UInt16 {
X86
X32
X64
X86_64 = X64
}
type OS = enum UInt16 {
LINUX
}
type BinaryFormat = enum UInt16 {
ELF
}
type Triple = struct {
arch: Arch
os: OS
binfmt: BinaryFormat
}
type CompilerImpl = interface {
method compile(o: io::Sink, file: spdr::ast::File)
}
var mu: sync::Mutex
var registry: Map#[Triple,CompilerImpl] #protectedBy(mu)
type Compiler = struct {
triple: Triple
impl: CompilerImpl
includeDirs: List#[String]
}
func addArguments(parser: argparse::ArgumentParser) {
parser.add(
argparse::FlagArgument.new(
name: 'spdr.compiler.arch',
long: 'arch',
help: 'target architecture',
type: Arch,
default: Arch.parse(runtime::currentArch)))
parser.add(
argparse::FlagArgument.new(
name: 'spdr.compiler.os',
long: 'os',
help: 'target operating system',
type: OS,
default: OS.parse(runtime::currentOS)))
parser.add(
argparse::FlagArgument.new(
name: 'spdr.compiler.binfmt',
long: 'binfmt',
help: 'target binary format',
type: BinaryFormat,
default: BinaryFormat.parse(runtime::currentBinaryFormat)))
parser.add(
argparse::FlagArgument.new(
name: 'spdr.compiler.include',
short: 'I',
long: 'include',
help: 'directory to search for imports',
repeatable: true))
}
method Compiler.init(args: argparse::Arguments) {
triple := Triple.new(
arch: args['spdr.compiler.arch'].parseValue(Arch),
os: args['spdr.compiler.os'].parseValue(OS),
binfmt: args['spdr.compiler.binfmt'].parseValue(BinaryFormat),
)
impl := lock mu {
return registry[triple]
}
if !impl {
throw StringError.new("unknown triple: %s", triple)
}
this.triple = triple
this.impl = impl
this.includeDirs = List#[string].new()
this.includeDirs.extend(args['spdr.compiler.include'].stringList())
}
method Compiler.compile(in: string, out: string) {
with inFile := os::Open(path: in, flags: os::O_RDONLY) {
ast := spdr::parser::parseFile(file: inFile)
ast.resolveIncludes(includeDirs: this.includeDirs)
with (outFile := os::Open(path: out, flags: os::O_WRONLY|os::O_CREATE|os::O_TRUNC, mode: 0o777)) {
this.impl.compile(o: outFile, file: ast)
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment