Skip to content

Commit

Permalink
Codegen: list pattern
Browse files Browse the repository at this point in the history
  • Loading branch information
ivanjermakov committed Apr 21, 2024
1 parent af8a009 commit e61e773
Showing 1 changed file with 28 additions and 14 deletions.
42 changes: 28 additions & 14 deletions src/codegen/js/expr.ts
Original file line number Diff line number Diff line change
Expand Up @@ -138,6 +138,7 @@ export const emitUnaryExpr = (unaryExpr: UnaryExpr, ctx: Context): EmitExpr => {
}
}
case 'await-op': {
// TODO
return { emit: emitToken(''), resultVar: jsError('bind-op').value }
}
}
Expand Down Expand Up @@ -200,6 +201,7 @@ export const emitOperand = (operand: Operand, ctx: Context): EmitExpr => {
}
}
case 'if-let-expr':
// TODO
return { emit: jsError('if-let'), resultVar }
case 'while-expr': {
const { emit: cEmit, resultVar: cVar } = emitExpr(operand.condition, ctx)
Expand Down Expand Up @@ -334,7 +336,7 @@ export const emitIdentifier = (identifier: Identifier, ctx: Context): EmitExpr =
return { emit: emitTree([upcastEmit]), resultVar }
}

export const emitLiteral = (operand: Operand, ctx: Context, resultVar: string): EmitExpr => {
export const emitLiteral = (operand: Operand, ctx: Context, resultVar?: string): EmitExpr => {
let constructorEmit: string
switch (operand.kind) {
case 'string-literal':
Expand All @@ -355,7 +357,11 @@ export const emitLiteral = (operand: Operand, ctx: Context, resultVar: string):
default:
return unreachable()
}
return { emit: emitTree([jsVariable(resultVar, emitToken(constructorEmit))]), resultVar }
if (resultVar) {
return { emit: emitTree([jsVariable(resultVar, emitToken(constructorEmit))]), resultVar }
} else {
return { emit: emitToken(''), resultVar: constructorEmit }
}
}

export const emitMatchExpr = (matchExpr: MatchExpr, ctx: Context, resultVar: string): EmitExpr => {
Expand All @@ -365,8 +371,8 @@ export const emitMatchExpr = (matchExpr: MatchExpr, ctx: Context, resultVar: str
return { emit: emitToken(''), resultVar }
}
const clauses = matchExpr.clauses.map(clause => {
if (clause.patterns.length !== 1) return jsError('union clause')
// TODO: union clauses
if (clause.patterns.length !== 1) return jsError('union clause')
const pattern = clause.patterns[0]
const cond = emitPatternExprCondition(pattern.expr, ctx, sVar)
const condGuarded: EmitExpr | undefined = clause.guard ? emitExpr(clause.guard, ctx) : undefined
Expand All @@ -378,7 +384,7 @@ export const emitMatchExpr = (matchExpr: MatchExpr, ctx: Context, resultVar: str
emitToken(`break ${breakLabel};`),
condGuarded ? emitToken('}') : undefined
])
return emitTree([cond.emit, emitTree([emitToken(`if(${cond.resultVar}){`), block, emitToken('}')])])
return emitTree([emitToken(`if(${cond}){`), block, emitToken('}')])
})
return {
emit: emitTree([
Expand All @@ -392,31 +398,38 @@ export const emitMatchExpr = (matchExpr: MatchExpr, ctx: Context, resultVar: str
}
}

export const emitPatternExprCondition = (patternExpr: PatternExpr, ctx: Context, sVar: string): EmitExpr => {
const resultVar = nextVariable(ctx)
export const emitPatternExprCondition = (patternExpr: PatternExpr, ctx: Context, sVar: string): string => {
switch (patternExpr.kind) {
case 'con-pattern': {
const variantName = patternExpr.identifier.names.at(-1)!.value
const cond = emitToken(`${sVar}.$noisVariant===${jsString(variantName)}`, patternExpr.identifier.parseNode)
const cond = `${sVar}.$noisVariant===${jsString(variantName)}`
// TODO: nested patterns
return { emit: jsVariable(resultVar, cond), resultVar }
return cond
}
case 'list-pattern':
return { emit: jsVariable(resultVar, jsError('list-pattern')), resultVar }
// TODO
const conds = [
`${sVar}.value.length===${patternExpr.itemPatterns.length}`,
...patternExpr.itemPatterns.map((p, i) => {
// TODO: equality is too strict, needs a special case for con patterns
return emitPatternExprCondition(p.expr, ctx, `${sVar}.value[${i}]`)
})
]
return conds.join('&&')
case 'hole':
return { emit: jsVariable(resultVar, emitToken('true')), resultVar }
return 'true'
case 'string-literal':
case 'char-literal':
case 'int-literal':
case 'float-literal':
case 'bool-literal': {
const operandEmit = emitOperand(patternExpr, ctx)
const literalEmit = emitLiteral(patternExpr, ctx)
// safe value equality check, since it is limited to builtin types
const cond = emitToken(`${sVar}.value===${operandEmit.resultVar}.value`)
return { emit: emitTree([operandEmit.emit, jsVariable(resultVar, cond)]), resultVar }
return `${sVar}.value===${literalEmit.resultVar}.value`
}
case 'string-interpolated':
return { emit: jsVariable(resultVar, jsError('string-interpolated')), resultVar }
// TODO
return jsError('string-interpolated').value
case 'name':
return unreachable()
}
Expand Down Expand Up @@ -466,6 +479,7 @@ export const emitPattern = (pattern: Pattern, ctx: Context, assignVar: string, p
return emitTree([...patterns])
case 'string-interpolated':
case 'list-pattern':
// TODO
return emitToken(`${jsError(pattern.expr.kind).value};`)
case 'string-literal':
case 'char-literal':
Expand Down

0 comments on commit e61e773

Please sign in to comment.