1 package org.simantics.scl.compiler.elaboration.java;
3 import org.cojen.classfile.TypeDesc;
4 import org.osgi.service.component.annotations.Component;
5 import org.simantics.scl.compiler.commands.CommandSession;
6 import org.simantics.scl.compiler.common.names.Name;
7 import org.simantics.scl.compiler.compilation.CompilationContext;
8 import org.simantics.scl.compiler.constants.JavaMethod;
9 import org.simantics.scl.compiler.elaboration.contexts.SimplificationContext;
10 import org.simantics.scl.compiler.elaboration.expressions.EApply;
11 import org.simantics.scl.compiler.elaboration.expressions.EExternalConstant;
12 import org.simantics.scl.compiler.elaboration.expressions.ELiteral;
13 import org.simantics.scl.compiler.elaboration.expressions.Expression;
14 import org.simantics.scl.compiler.elaboration.macros.MacroRule;
15 import org.simantics.scl.compiler.elaboration.modules.SCLValue;
16 import org.simantics.scl.compiler.internal.codegen.types.StandardTypeConstructor;
17 import org.simantics.scl.compiler.module.ConcreteModule;
18 import org.simantics.scl.compiler.types.TCon;
19 import org.simantics.scl.compiler.types.Type;
20 import org.simantics.scl.compiler.types.Types;
21 import org.simantics.scl.compiler.types.kinds.Kinds;
22 import org.slf4j.Logger;
23 import org.slf4j.LoggerFactory;
24 import org.slf4j.Marker;
27 public class LoggingModule extends ConcreteModule {
29 private static final String[] LOGGING_METHODS = new String[] {
30 "trace", "debug", "info", "warn", "error"
33 public static final TCon Throwable = Types.con("Prelude", "Throwable");
35 public LoggingModule() {
39 TCon Logger = Types.con(getName(), "Logger");
40 StandardTypeConstructor loggerConstructor = new StandardTypeConstructor(Logger, Kinds.STAR, TypeDesc.forClass(Logger.class));
41 loggerConstructor.external = true;
42 addTypeDescriptor("Logger", loggerConstructor);
45 TCon Marker = Types.con(getName(), "Marker");
46 StandardTypeConstructor markerConstructor = new StandardTypeConstructor(Marker, Kinds.STAR, TypeDesc.forClass(Marker.class));
47 markerConstructor.external = true;
48 addTypeDescriptor("Marker", markerConstructor);
51 Type isEnabledType = Types.functionE(Types.PUNIT, Types.PROC, Types.BOOLEAN);
52 Type loggingType = Types.functionE(Types.STRING, Types.PROC, Types.UNIT);
53 Type loggingTypeWithMarker = Types.functionE(new Type[] { Marker, Types.STRING }, Types.PROC, Types.UNIT);
54 Type loggingTypeWithException = Types.functionE(new Type[] { Types.STRING, Throwable }, Types.PROC, Types.UNIT);
55 Type loggingTypeWithMarkerAndException = Types.functionE(new Type[] { Marker, Types.STRING, Throwable }, Types.PROC, Types.UNIT);
57 // Add logging methods
58 for(String methodName : LOGGING_METHODS) {
59 { // isEnabled :: <Proc> Boolean
60 String completeMethodName = generateIsEnabledName(methodName);
61 JavaMethod javaMethod = new JavaMethod(false, "org/slf4j/Logger", completeMethodName, Types.PROC, Types.BOOLEAN, Logger);
62 SCLValue value = new SCLValue(Name.create(getName(), completeMethodName));
63 value.setType(isEnabledType);
64 value.setMacroRule(new MacroRule() {
66 public Expression apply(SimplificationContext context, Type[] typeParameters, EApply apply) {
67 String identifier = resolveModuleIdentifier(context.getCompilationContext());
68 apply.set(new ELiteral(javaMethod), new Expression[] {
69 new EExternalConstant(LoggerFactory.getLogger(identifier), Logger)
76 { // logging function with single String-parameter :: String -> <Proc> ()
77 JavaMethod javaMethod = new JavaMethod(false, "org/slf4j/Logger", methodName, Types.PROC, Types.UNIT, Logger, Types.STRING);
78 SCLValue value = new SCLValue(Name.create(getName(), methodName));
79 value.setType(loggingType);
80 value.setMacroRule(new MacroRule() {
82 public Expression apply(SimplificationContext context, Type[] typeParameters, EApply apply) {
83 String identifier = resolveModuleIdentifier(context.getCompilationContext());
84 apply.set(new ELiteral(javaMethod), new Expression[] {
85 new EExternalConstant(LoggerFactory.getLogger(identifier), Logger),
93 { // logging function with two parameters :: String -> Throwable -> <Proc> ()
94 JavaMethod javaMethod = new JavaMethod(false, "org/slf4j/Logger", methodName, Types.PROC, Types.UNIT, Logger, Types.STRING, Throwable);
95 SCLValue value = new SCLValue(Name.create(getName(), methodName + "E"));
96 value.setType(loggingTypeWithException);
97 value.setMacroRule(new MacroRule() {
99 public Expression apply(SimplificationContext context, Type[] typeParameters, EApply apply) {
100 String identifier = resolveModuleIdentifier(context.getCompilationContext());
101 apply.set(new ELiteral(javaMethod), new Expression[] {
102 new EExternalConstant(LoggerFactory.getLogger(identifier), Logger),
111 { // logging function with two parameters :: Marker -> String -> <Proc> ()
112 JavaMethod javaMethod = new JavaMethod(false, "org/slf4j/Logger", methodName, Types.PROC, Types.UNIT, Logger, Marker, Types.STRING);
113 SCLValue value = new SCLValue(Name.create(getName(), methodName + "M"));
114 value.setType(loggingTypeWithMarker);
115 value.setMacroRule(new MacroRule() {
117 public Expression apply(SimplificationContext context, Type[] typeParameters, EApply apply) {
118 String identifier = resolveModuleIdentifier(context.getCompilationContext());
119 apply.set(new ELiteral(javaMethod), new Expression[] {
120 new EExternalConstant(LoggerFactory.getLogger(identifier), Logger),
129 { // logging function with three parameters :: Marker -> String -> Throwable -> <Proc> ()
130 JavaMethod javaMethod = new JavaMethod(false, "org/slf4j/Logger", methodName, Types.PROC, Types.UNIT, Logger, Marker, Types.STRING, Throwable);
131 SCLValue value = new SCLValue(Name.create(getName(), methodName + "ME"));
132 value.setType(loggingTypeWithMarkerAndException);
133 value.setMacroRule(new MacroRule() {
135 public Expression apply(SimplificationContext context, Type[] typeParameters, EApply apply) {
136 String identifier = resolveModuleIdentifier(context.getCompilationContext());
137 apply.set(new ELiteral(javaMethod), new Expression[] {
138 new EExternalConstant(LoggerFactory.getLogger(identifier), Logger),
150 setParentClassLoader(LoggerFactory.class.getClassLoader());
153 private static String generateIsEnabledName(String level) {
154 return "is" + capitalizeFirstCharacter(level) + "Enabled";
157 private static String capitalizeFirstCharacter(String input) {
158 return input.substring(0, 1).toUpperCase() + input.substring(1);
161 private static String resolveModuleIdentifier(CompilationContext context) {
162 ConcreteModule module = context.module;
164 if (module != null) {
165 String moduleName = module.getName();
166 if (moduleName.startsWith("http://")) {
167 moduleName = moduleName.substring("http://".length());
169 identifier = moduleName.replaceAll("/", ".");
171 identifier = CommandSession.class.getName();