Skip to content

Commit

Permalink
Codegen: compile single source file
Browse files Browse the repository at this point in the history
  • Loading branch information
ivanjermakov committed Mar 5, 2024
1 parent c447646 commit c9c10a3
Show file tree
Hide file tree
Showing 2 changed files with 47 additions and 25 deletions.
7 changes: 5 additions & 2 deletions data/example.no
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
use std::{ math::pi, iter::MapAdapter }

trait Area {
fn area(self): Float
}
Expand All @@ -10,8 +12,8 @@ type Shape {
impl Area for Shape {
fn area(self): Float {
match self {
Shape::Rect(width, height) { width * height },
Shape::Circle(radius) { math::pi * radius ^ 2. }
Shape::Rect(width, height) { width * height }
Shape::Circle(radius) { pi * radius ^ 2. }
}
}
}
Expand All @@ -23,3 +25,4 @@ fn main() {
]
println(shapes.iter().map(Area::area).collect<List<_>>())
}

65 changes: 42 additions & 23 deletions src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ export const usage = `\
${usageHeader}
Usage: noisc [OPTIONS] FILE
If FILE is a directory, compile files at FILE/<src> into FILE/<out> directory with <deps> in scope
If FILE is a directory, compile source files at <src> into <out> directory with <deps> in scope
If FILE is a source file, compile it into <out> directory
Options:
--name=<name> Compile package with this name
Expand Down Expand Up @@ -56,7 +56,8 @@ if (!existsSync(config.pkgPath)) {
console.error(`no such file \`${config.pkgPath}\``)
process.exit(1)
}
if (statSync(config.pkgPath).isDirectory()) {
const isDir = statSync(config.pkgPath).isDirectory()
if (isDir) {
const srcPath = join(config.pkgPath, config.srcPath)
if (!existsSync(srcPath)) {
console.error(`no such file \`${srcPath}\``)
Expand Down Expand Up @@ -152,33 +153,51 @@ for (const warning of ctx.warnings) {
}

if (config.emit) {
if (!existsSync(config.outPath)) mkdirSync(config.outPath, { recursive: true })
const packageInfoSrc = join(config.pkgPath, 'package.json')
const packageInfoDest = join(config.outPath, 'package.json')
copyFileSync(packageInfoSrc, packageInfoDest)
console.info(`copy: ${packageInfoSrc} -> ${packageInfoDest}`)
pkg.modules.forEach(m => {
ctx.variableCounter = 0
const modulePath = relative(config.srcPath, m.source.filepath)
const moduleOutPath = parse(join(config.outPath, modulePath))
if (!existsSync(moduleOutPath.dir)) mkdirSync(moduleOutPath.dir)

const declaration = emitDeclaration(m)
const declarationPath = join(moduleOutPath.dir, moduleOutPath.name) + '.no'
writeFileSync(declarationPath, declaration)
console.info(`emit: declaration ${declarationPath} [${declaration.length}B]`)

const nativePath = m.source.filepath.replace(/\.no$/, '.js')
const native = existsSync(nativePath) ? readFileSync(nativePath) : ''
if (isDir) {
if (!existsSync(config.outPath)) mkdirSync(config.outPath, { recursive: true })
const packageInfoSrc = join(config.pkgPath, 'package.json')
if (!existsSync(packageInfoSrc)) {
console.error(`${packageInfoSrc} not found`)
process.exit(1)
}
const packageInfoDest = join(config.outPath, 'package.json')
copyFileSync(packageInfoSrc, packageInfoDest)
console.info(`copy: ${packageInfoSrc} -> ${packageInfoDest}`)
pkg.modules.forEach(m => {
ctx.variableCounter = 0
const modulePath = relative(config.srcPath, m.source.filepath)
const moduleOutPath = parse(join(config.outPath, modulePath))
if (!existsSync(moduleOutPath.dir)) mkdirSync(moduleOutPath.dir)

const declaration = emitDeclaration(m)
const declarationPath = join(moduleOutPath.dir, moduleOutPath.name) + '.no'
writeFileSync(declarationPath, declaration)
console.info(`emit: declaration ${declarationPath} [${declaration.length}B]`)

const nativePath = m.source.filepath.replace(/\.no$/, '.js')
const native = existsSync(nativePath) ? readFileSync(nativePath) : ''
// TODO: custom main module and main fn name
const mainFn =
m.mod && m.identifier.names.length === 1
? m.block.statements.find(s => s.kind === 'fn-def' && s.pub && s.name.value === 'main')
: undefined
const mainFnName = mainFn?.kind === 'fn-def' ? mainFn.name.value : undefined
const js = [emitModule(m, ctx, mainFnName), native].filter(m => m.length > 0).join('\n\n')
const jsPath = join(moduleOutPath.dir, moduleOutPath.name) + '.js'
writeFileSync(jsPath, js)
console.info(`emit: js ${jsPath} [${js.length}B]`)
})
} else {
const m = pkg.modules[0]
// TODO: custom main module and main fn name
const mainFn =
m.mod && m.identifier.names.length === 1
? m.block.statements.find(s => s.kind === 'fn-def' && s.pub && s.name.value === 'main')
: undefined
const mainFnName = mainFn?.kind === 'fn-def' ? mainFn.name.value : undefined
const js = [emitModule(m, ctx, mainFnName), native].filter(m => m.length > 0).join('\n\n')
const jsPath = join(moduleOutPath.dir, moduleOutPath.name) + '.js'
const js = emitModule(m, ctx, mainFnName)
const jsPath = join(config.outPath, parse(config.pkgPath).name) + '.js'
writeFileSync(jsPath, js)
console.info(`emit: js ${jsPath} [${js.length}B]`)
})
}
}

0 comments on commit c9c10a3

Please sign in to comment.